Euler公佈了一个著名的公式:
n² + n + 41
当n = 0 ~ 39时它可以得到40个质数,不过当n = 40时,402 + 40 + 41 = 40(40 + 1) + 41可以被41整除,故当n = 41时得到的不是质数。
通过计算机分析,一个更不可思议的公式诞生了。n² - 79n + 1601能产生80个质数若n = 0 ~ 79。两个系数-79和1601的积是-126479。
现在来看看下面的公式:
n² + an + b且|a| < 1000, |b| < 1000
|n|表示n的绝对值,如|11| = 11|,|-4| = 4。
找出合适的系数a和b,使得当n从0开始递增时,得到最多的连续的质数项,并把a和b的积求出来。
这个题目求的问题就是,
这个公式中a和b的系数分别为多少,这个公式从0-x的解都为质数,且x是最大的;
那么开始分析:
1.b一定为正整数,并且为质数,因为当n等于0时
那么题目要解为质数,所以b一定为质数
2.a+b+1为正整数,并且为质数,因为当n等于1时
,上面同理;
那么通过这两个性质可以有效减少循环次数,下面是代码实现过程:
#include <stdio.h> #define MAX_N 1000 #define MAX_X 1000000 int prime[MAX_X + 5]; int primenum[MAX_X + 5]; void init() {//线性筛 prime[1] = 1; for (long long i = 2; i < MAX_X; i++) { if (!prime[i]) primenum[++primenum[0]] = i; for (long long j = 1; i * primenum[j] < MAX_X; j++) { prime[i * primenum[j]] = 1; if (i % primenum[j] == 0) break; } } } long long func(int a, int b, int x) { return x * x + a * x + b; } int main() { init();//运行线性筛 int ans = 0, ans_cnt = 0; for (int i = -999; i < 1000; i++) {//因为|a|<1000所以从-999开始 for (int j = (i < 0 ? (-i + 1) : 2); j < 1000; j++) {//因为i + j + 1必须大于0才可能为质数,所以a小于0时a + b > 0所以b = -a + 1 a大于0时b就正常从2开始,因为1不为质数 if (prime[j]) continue; if (prime[i + j + 1]) continue; int cnt = 0; int k = 0; while (1) { long long s = func(i, j, k);//用公式求得值 if (s <= 0 || prime[s]) break;//当s<=0他不可能为质数, prime[s] = 1他也不为质数所以直接结束循环 cnt++;//说明s是质数,计数加1 k++;//k就是公式中的n } if (cnt > ans_cnt) {//比较之前存下的值 ans = i * j; ans_cnt = cnt; } } } printf("%d\n", ans); return 0; }
最终答案:-59231