一 哥德巴赫猜想
哥德巴赫猜想可分为两种猜想,一种也称为“二重哥德巴赫猜想”,另一种就是“三重哥德巴赫猜想”。
具体为:1. 每个不小于6的偶数都可以表示为两个奇素数之和;
2. 每个不小于9的奇数都可以表示为三个奇素数之和;
ps:1 不是素数。
笔试有题,让输出6~10 0000 之间的偶数都可以用两个奇素数之和表示出来,即 a = b + c,程序输出b,和c,若满足条件的有多个组合,输出一组即可。【注意时间效率】
看到这题,首先想到的就是求素数,而且需要注意时间效率。
空间置换时间,那就求出小于10 0000的素数保存至数组,然后同时从头和尾扫描这个数组,b指向数组头,c指向数组尾,
若b+c==a,break;
若b+c > a, --b;
若b+c <a , ++c;
不管这种思路对错,首要问题是求素数。素数的英文名是啥来着??忘记了,%>_<% prime
二 求素数
编程求素数,一直都是梦魇,噩梦。因为,知道有很多种方法,但,书到用时方恨少。代码到写时,发现记住的太少(理解的太少)。简单回忆下集中求素数的方法。
1、简单朴素求素数方法
根据素数的定义,约数只有1和它本身的整数称为素数,假设一个整数为n,于是最简单的判断n是否是素数的方法就是从2到n-1都枚举一遍,判断是否存在能整数n的整数,如果都不能整除,ok,n为素数。
bool IsPrime(int n) { for (int i = 2; i < n; i++) { if (n % i == 0) { return false; } } return true; }
2、改进的求素数方法
第一种方法中,时间复杂度为O(n),因此必须进行改进。对于一个小于n的整数x,如果n能被x整除,因此n肯定能被n/x整除。
举例:如果n能够被2整除,写作 n 2 n/2
如果n能够被3整除,写作 n 3 n/3
如果n能够被4整除,写作 n 4 n/4
……
如果n能够被sqrt(n)整除,写作 n sqrt(n) sqrt(n)
代码如下:
bool IsPrime(int n) { for (int i = 2; i*i < n; i++) { if (n % i == 0) { return false; } } return true; }
通过分析可知,这个方法的时间复杂度为O(sqrt(n))
3. 筛选法
如果某个数m是另一个数n的倍数,则m肯定不是素数。所以我们可以在某个范围内,将已知素数的所有倍数都筛去,剩下的肯定都是素数,因为只有它不是其他数的倍数(1和它本身除外)。
具体做法是: 先把N个自然数按次序排列,1不是质数,也不是合数,要划去。
2是质数,保存。同时把后面的所有能被2整除的数都划去。
2后面第一个没划去的是3,把3留下,同时把3后面所有被3整除的数都划去。
3后面第一个没被划去的是5,把5留下,同时把5后面所有被5整除的数都划去。
这样一直做下去,就会把不超过N的全部合数筛掉,保留下来小于N的素数。
#define MAX 1000 bool isprime[MAX]; void ThePrimes() { int i,j; for (i = 2; i < MAX; i++) { isprime[i]=1; } for (i = 2; i < MAX; i++) { if (isprime[i]) { for (j = i+i; j < MAX; j+=i) { isprime[j] = 0; } } } }
执行完本算法后,isprime[i]==1,则说明i是素数。所以在O(1)时间内,能够判断MAX以内的任意数是否为素数。而且,该算法的时间复杂度为O(loglogn).
4、改进的筛选法
可以为筛选法增加一个数组,记录已经找到的素数,通过这些已经找到的素数,来筛掉后面的数,由于每个数都可以分解成质因数的形式,所以所有质因数都被筛掉后,自然不在素数列表中了。
#define MAX 1000 bool isprime[MAX]; int p[MAX]; void prime(int n) { memset(isprime,0,sizeof isprime); memset(p,0,sizeof p); int np=0; for (int i=2;i<=n;i++) { if(!isprime[i]) p[np++]=i; for (int j = 0;j<np&&p[j]*i<=n;j++) { isprime[p[j]*i] = 1; if(i%p[j]==0) break; } } }
5、可以先求出sqrt(n),内的素数,然后进行筛选。此处不写代码了。
利用上述五种方法中的一种,计算出素数,然后扫描即可。
但是,10 0000 这个算是大数据了。用此种方法不妥。还不如分别找N/2,左右的素数,b 为小于N/2的最大素数,c为大于N/2的最小素数,比较a?=b+c,不等的话,就继续找合适的b和c的值。
int i = 1; i < N/2; i++
{
if(isprime(N/2-i)&&isprime(N/2+i))
{ 输出即可}
}
先到这儿吧