木哈哈~咩哈哈~
终于写出了一个经过深思熟虑才写出的代码~好久没有这种感觉了!!
题目大意就是欧拉大神找到这样一个公式,n^2+n+41, 这个公式的神奇之处在于,n in range(0, 40) 满足return的value全都是prime
这个非常神奇,真心不知道他怎么算的……
题目还给出了另外一个公式,n^2-79n+1601, 这也是神奇公式,n in range(0 80) ,同上述。
题目要求我们算出,n^2+an+b 保证尽量多的n,从n=0开始,连续的。(艹……中文不会讲了……英语也不会讲……)
Find the product of the coefficients, a and b,
for the quadratic expression that produces the maximum number of primes for consecutive values of n,
starting with n =
0.
同时,where |a| 1000
and |b|
1000
嗯,我是这样分析的
首先,n从0开始,那么第一项就是 0+0+b,那么b肯定要是一个质数。而且是一个正的质数,b<0情况不用考虑啦~
第二,n=1,1+a+b肯定要保证是个质数,那才有算下去的必要。所以,a> -b-1(这里写成1-b也行,为什么呢?哈~)
第三,因为欧拉给出了一个式子,我们要算的肯定比他多,那么一个优化就是,40^2+40a+b>0 => a > -b/40 -40
在这两个限制条件中,选一个大的,算作min_a,然后暴力枚举n。(n最大不会超过80的!)
当然,首先要把prime numnber都算出来,O(nlogn)
这样总共时间复杂度应该大约是O(1000*log1000+m*1000*80)神马神马的……随便写写,m表示小于1000的prime number个数。
肯定会挺快的啦~
下面上代码,有些可以优化的细节,就直接忽略了……
#include <stdio.h>
#define SIZE 30000
int prime[SIZE];
int prime_list[10000];
int n_prime;
int
findPrime()/*比较经典的数素数,筛法选素数*/
{
int i, j;
int *p;
p = prime_list;
for (i=0; i<SIZE; i++)
prime[i] = 1;
prime[0] = 0; prime[1] = 0;
i = 2; *p = 2; j = i*i;
while (j<SIZE)
{
prime[j] = 0;
j += i;
}
for (i=3; i<SIZE; i +=2)
if (prime[i])
{
*(++p) = i;
j = i*i;
while (j<SIZE)
{
prime[j] = 0;
j += i;
}
}
n_prime = p - prime_list;
return 0;
}
int
calcFormula(int a, int b)
{
int n, tmp;
for (n=0; n<100; n++)
{
tmp = n*n + a*n + b;
if (!prime[tmp])
{
return n;
}
}
return 0;
}
int
main()
{
int max = 0;
int a, b, i;
int now, min_a, num, xa, xb;
findPrime();
max = 0;
for (i=12; i<n_prime; i++)
{
b = prime_list[i];
if (b >= 1000)
break;
min_a = -b/40 - 40;
min_a = min_a < (1-b) ? (1-b) : min_a;
num = 0;
for (a=min_a; a<1000; a++)
{
now = calcFormula(a, b);
if (now > max)
{
max = now;
xa = a;
xb = b;
}
}
}
printf("%d, %d, %d", max, xa, xb);
return 0;
}
用时
$ time ./a
71, -61, 971
real 0m0.063s
user 0m0.000s
sys 0m0.000s