518 Prime Triples and Geometric Sequences
,其中 满足以下三个性质的所有元组 1. 都是质数 2. 3. 能组成等比数列
题目中给出了一个例子 可以用于测试。
求
前一亿个数里面有 576 万个质数,显然,不可以接受 的算法。
为了描述方便,后面 是题目中的 。
能组成等比数列,那么 。
给定一个 ,我们不能用遍历的方式去找 ,否则会是 的算法。我们需要一个更快的方式找到可能的 。
考虑这样一个问题, 的质因数里面有 4 个 ,那么 的质因数里面至少有 2 个 ,那么 和 之间最少也相差 ; 的质因数里面有 个 ,那么 的质因数里面至少有 3 个 ,那么 和 之间最少也差着 ;同时考虑 和 的话,那么差值是 。有了这个差值,就能够大大减少内层循环的数目。通过计数器发现,内层循环大概是 8-9次。
问题转换到如何得到 的质因数及其次数,这是一个比较简单的问题。
public static List<Tuple<long, int>> TrialDivisioFactor(long n, long[] primes)
{
var results = new List<Tuple<long, int>>();
int index = 0;
while (true)
{
if (primes[index] != 0)
{
if (primes[n] != 0)
{
results.Add(new Tuple<long, int>(n, 1));
break;
}
int count = 0;
while (n % primes[index] == 0)
{
count++;
n /= primes[index];
}
if (count != 0)
{
results.Add(new Tuple<long, int>(primes[index], count));
}
if (n == 1)
{
break;
}
}
index++;
}
return results;
}
GenPrimes
就是通过筛选法得到质数。
int end = 100000000;
long sum = 0;
Utils.GenPrimes(end, out long[] primes);
for (int i = 0; i < primes.Length; i++)
{
if (primes[i] != 0)
{
var a = primes[i] + 1;
var factors = Utils.TrialDivisioFactor(a, primes);
var step = 1;
foreach (var f in factors)
{
step *= (int)Math.Pow(f.Item1, (f.Item2 + 1) / 2);
}
for (long b = a + step; b < end; b += step)
{
var c = b * b / a;
if (c >= end)
{
break;
}
if (primes[b - 1] != 0 && primes[c - 1] != 0)
{
sum += a + b + c - 3;
}
}
}
}
return sum;