Project Euler 27

本文介绍了一个寻找特定二次表达式的问题,该表达式能产生最大数量的连续质数。通过对欧拉发现的公式进行分析,文章提出了求解a和b系数的方法,并通过编程实现了算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

木哈哈~咩哈哈~


终于写出了一个经过深思熟虑才写出的代码~好久没有这种感觉了!!


题目大意就是欧拉大神找到这样一个公式,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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值