素数判断算法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
首先,介绍一下求 1~n 范围内的素数的筛选法: 素数筛选法,也称“埃拉托色尼(Eratosthenes)筛法”,埃拉托色尼是古希腊著名的数
学家(膜拜一下)。素数筛选法操作如下,首先从 2 开始,将 2+k(k=1,2,3,……n-2) 都对 2 进行整除运算,若(2+k)能整出 2,说明这个数一定是合数,那就将它筛掉;然后
根据前面的数学知识可以了解到,如果用小于等于 n 的素数来判断 n 是否为素数即
可。在实际操作中,假设 a 为素数,那筛选时,直接从 a 2 开始,将 a 2 +a*i(i=0,1,2,3……)
筛选掉即可,直至 i+1 后恰好使 a 2 +a*i>=n 为止。就不需要判断某一个数是否会被素数整
出了。这样每个被筛选掉的数字只用了一次计算,而那些素数并没有经过整除判断。 最后,我们按照上面的思路将代码写出来。 看代码: #include<cstring> #include<iostream> #define max 10000 using namespace std;
判断素数
一个数 n 如果是合数,那么它的所有的因子不超过 sqrt(n)--n 的开方,那么我们可 以用这个性质用最直观的方法 来求出小于等于 n 的所有的素数。
num = 0; for(i=2; i<=n; i++) { for(j=2; j<=sqrt(i); j++)
if( j%i==0 ) break; if( j>sqrt(i) ) prime[num++] = i; //这个 prime[]是 int 型,跟下 面讲的不同。 } 这就是最一般的求解 n 以内素数的算法。复杂度是 o(n*sqrt(n))。 但我不认为这是算法。 根据定义来进行判定,无法体现出算法的魅力!既然如此,喜欢算法那就用优美的算法 来解决这个问题。
} k=0; for(j=2;j<max;j++)
if(p[j]) prim[k++]=j; for(j=0;j<k;j++) cout<<j<<" "<<prim[j]<<endl; return 0; }
对于素数问题,历史上有许多猜想和论证,部分如下: 最大公约数只有 1 和它本身的数叫做质数(素数)。 至今为止,没有任何人发现素数的分布规律,也没有人能用一个公式计算出所有的素数。 关于素数的很多的有趣的性质或者科学家的努力: 1.高斯猜测,n 以内的素数个数大约与 n/ln(n)相当,或者说,当 n 很大时,两者数量 级相同。这就是著名的素数定理。 2.十七世纪费马猜测,2 的 2^n 次方+1,n=0,1,2…时是素数,这样的数叫费马素数, 可惜当 n=5 时,2^32+1 就不是素数,至今也没有找到第六个费马素数。 3.18 世纪发现的最大素数是 2^31-1,19 世纪发现的最大素数是 2^127-1,20 世纪末人 类已知的最大素数是 2^859433-1,用十进制表示,这是一个 258715 位的数字。 4.孪生素数猜想:差为 2 的素数有无穷多对。目前知道的最大的孪生素数是 1159142985 ×2^2304-1 和 1159142985×2^2304+1。 5.歌德巴赫猜想:大于 2 的所有偶数均是两个素数的和,大于 5 的所有奇数均是三个素 数之和。其中第二个猜想是第一个的自然推论,因此歌德巴赫猜想又被称为 1+1 问题。我国 数学家陈景润证明了 1+2,即所有大于 2 的偶数都是一个素数和只有两个素数因数的合数的 和。国际上称为陈氏定理。
于 n ;如果 n 为素数,那 n 的因子只有 1 和它本身(定义)。前一部分可以用
反证法证明,在这不再赘述。 接着,我们对这个算法进行优化: 在筛选的时候,我们发现,按照上面的流程,同一个素数数会被许多个素数进行判断, 而实际上,我们通过观察发现,2 的筛选是从 4 开始的,凡是大于 2 且为 2 的倍数的数字都 被筛选掉了,3 是从 9 开始筛选的,凡是剩下的大于 3 且为 3 的倍数的数字都被筛选掉了……
…… ……
最终结果:
1
2
3
4
5
ቤተ መጻሕፍቲ ባይዱ
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
剩下的黑色的就是素数(1 除外)。
这个算法相比于用定义判断素数要快很多倍。 用数学来解释:
1, n(n>1)的因子,小于等于 n ;
2, 如果 n 为合数,那 n 的所有因子中一定存在素数因子,素数因子也满足小于等
int main() {
bool p[max]={ 0,0,1,1,0,1}; int prim[max]={0}; int j,k=2; memset(p,1,sizeof(p)); for(j=2;j<max;j++)
{ if(p[j]) for(k=j*j;k<max;k+=j) p[k]=0;
找下一个没有被筛选掉的数字开始,就是从 3 开始,剩下的数字对 3 进行整除运算,如果某 一个数能整除 3,则将其筛掉,接下来,按照这个模式一直筛选,直至 n 做除数。
用表格表示一下筛选过程(1~30):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1, 用 2 筛选(红色的就是被筛掉的数字):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2, 用下一个没有被没有被筛选掉的数字筛选:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
(蓝色的就是此次筛选掉的数字) ……