您的位置:首页 > 其它

素数算法吐血总结

2017-12-17 22:07 141 查看

扯淡

相信很多童鞋在OJ都遇到过关于素数的问题,对于素数相关问题,一般都会给出答案,但是相信并不是所有人能给出最优解,包括本菜鸟,故吐血整理一波,以供学习回顾。

素数定义

既然都说素数、质数什么的,那么什么是素数呢?

质数(Prime number),又称素数,指在大于1的自然数中,除了1和该数自身外,无法被其他自然数整除的数(也可定义为只有1与该数本身两个正因数的数)。大于1的自然数若不是素数,则称之为合数。

问题

对于素数相关问题,一般会有三种问题。

判断某个数是否为素数。

打印出小于自然数
N
的素数。

对于给定的自然数
N
,从小到大依次打印出
N
个素数。

素数判断

试除法

如果要判断某个自然数
X
是否为素数,,这就是试除法

初级版

假设要判断自然数
X
是否为素数,最简单的想法就是判断
X
是否能够整除
1
~
X
之间的某个数。

中级版

如果自然数
X
存在质因数,那么必定会小于等于
X/2
, 所以稍微动脑的人会将返回缩小到
1
~
X/2
, 减小一半的工作量

高级版

对于一个自然数,如果存在可整除的数,即
X = a * b
, 那么因数中必定会有一个因数小于X‾‾√X, 而另一个因数大于X‾‾√X。 故很多更聪明的程序猿会将返回缩小到
1
~ X‾‾√X

上面的算法仅仅是判断某个数是否为质数,可是要得出素数的序列,仅仅通过遍历自然数然后进行素数判断可是最傻的办法,那么有什么简单高效的算法呢?

筛法

质数算法中的重头戏就是要说的本算法。

埃拉托斯特尼筛法

基本思想

素数的倍数一定不是素数。

做法

首先申请空间为
N+1
的数组用来保存自然数
1 ~ N
是否为质数,起初将所有自然数全部置为
0
, (
0
表示质数,
1
表示合数),从第一个素数
2
开始,将
2
的倍数全部置为
1
, 然后找到下一个素数
3
,将
3
的倍数全部置为
1
, 直到找到最后一个小于
N
的质数。此处引用维基百科的示例图。



代码实现

void make_prime()
{
memset(prime, 1, sizeof(prime));
prime[0] = false;
prime[1] = false;
int N = 31700;
for (int i = 2;  i < N;  i++)
if (prime[i])
{
primes[++cnt ] = i;
for (int k = i + i; k < N; k += i)
prime[k] = false;
}
return;
}


时间复杂度为O(nloglogn), 空间复杂度为O(n)

虽然已经很高效,但是仍然存在缺点,对于能够整除不同素数的自然数,筛了多次。例如
30
, 在素数
2
的时候,
k = 2 * 15
筛过一次,素数为
3
的时候,
k = 3 * 10
又筛过一次。故出现了下面的改进算法。

欧拉筛法

const long N = 200000;
long prime
= {0}, num_prime = 0;
int isNotPrime
= {1, 1};
int main()
{
for (long i = 2 ; i < N ; i ++)
{
if (! isNotPrime[i])
prime[num_prime ++] = i;
//关键处1
for (long j = 0 ; j < num_prime && i * prime[j] <  N ; j ++)
{
isNotPrime[i * prime[j]] = 1;
if ( !(i % prime[j] ) ) //关键处2
break;
}
}
return 0;
}


理解

首先,先明确一个条件,任何合数都能表示成一系列素数的积。 不管 i 是否是素数,都会执行到“关键处1”。

如果 i 都是是素数的话,那简单,一个大的素数 i 乘以不大于 i 的素数,这样筛除的数跟之前的是不会重复的。筛出的数都是 N=p1*p2的形式, p1,p2之间不相等

如果 i 是合数,此时 i 可以表示成递增素数相乘 i=p1p2…*pn, pi都是素数(2<=i<=n), pi<=pj ( i<=j ) p1是最小的系数。

根据“关键处2”的定义,当p1==prime[j] 的时候,筛除就终止了,也就是说,只能筛出不大于p1的质数*i。

我们可以直观地举个例子:i=2*3*5 此时能筛除 2*i ,不能筛除 3*i, 如果能筛除3*i 的话,当 i’ 等于 i’=3*3*5 时,筛除2*i’ 就和前面重复了。

引用

埃拉托斯特尼筛法

求质数算法的 N 种境界[1] - 试除法和初级筛法

数论——筛法求素数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法