800 Hybrid Integers
原题链接:https://projecteuler.net/problem=800
一个整数形如 称为 hybrid-integer
。
比如 就是 hybrid-integer
。
定义 是小于等于 的 hybrid-integer
个数。
比如 。
求 。
这个题目可以使用 double
这种非精确的小数表示,因为 这两个边界值不是 hybrid-integer
。前者可以写作
而后者的质因数有 。
不妨设 ,给定 ,有多少个 hybrid-integer
呢?也就是求满足下面条件 的个数。
将 看做是变量,这是一个递增函数,也就是要找到最小的不满足条件的 ,然后 之间的质数个数即可。
两边取对数(底数不重要) 左边第二项是正数,可以稍微放宽条件,将其减少一点
由于需要得到 之间的质数个数,需要一个质数的列表。在计算之前,我们需要知道需要多少个质数。使用 2 作为底数,极端情况下
后面的事情就比较简单了。
1. 从 2 开始遍历,直到
2. 根据 计算 ,这时 有可能不满足条件,太大了,然后开始往下减直到满足条件
3. 计算当前 之间的质数个数
var primes = Utils.GenPrimes(15710000).Where(l => l != 0).ToArray();
long count = 0;
int pindex = 0;
while (true)
{
int p = (int)primes[pindex];
int q = (int)(M * Math.Log(M, p)) + 1;
if (q <= p)
{ break; }
int qindex = Array.BinarySearch(primes, q);
if (qindex < 0)
qindex = ~qindex;
q = (int)primes[qindex];
while (true)
{
if (q * Math.Log(p) + p * Math.Log(q) < M * Math.Log(M))
{ break; }
qindex--;
q = (int)primes[qindex];
if (qindex <= pindex)
{ break; }
}
if (qindex > pindex)
count += qindex - pindex;
pindex++;
}
其实
Math.Log
不需要反复计算。
右边的是个定值,计算一次即可,左边的 就是最开始生成的质数,那么可以提前计算好,后面用就好了。