1.(nlogn):
bool not_prime[2333]=false;
//把非质数都设为false,如果not_prime为false,则是质数,为true,则不是质数
not_prime[1]=true;
for(int a=2;a<=n;a++)
for(int b=a+a;b<=n;b+=a)
not_prime[b]=true;
//是a的倍数的数b全部是非质数,即not_prime[b]=true;
/*b从2a开始,每次+a,直到题目给定的范围n结束
a=2的时候,b一共+n/2次
a=3的时候,b一共+n/3次
...
a=n的时候,b一共+n/n次
那么整体时间复杂度就是:
n*(n/2+n/3+...+n/n)
≈n*(n/1+n/2+n/3+...+n/n)
≈nlogn
注:n/1+n/2+n/3+...+n/n为调和级数,其值约为logn,有兴趣自查*/
/*我们知道,筛4的时候,4的倍数已经在2中筛完了
筛6的时候,6的倍数已经在3中筛完了
以此类推,合数的倍数将在前面筛完了
那么我们就有如下小优化:*/
bool not_prime[2333]=false;
not_prime[1]=true;
for(int a=2;a<=n;a++)
if(not_prime[a]==false)
for(int b=a+a;b<=n;b+=a)
not_prime[b]=true;
当然,即使优化后也会有被多次筛掉的部分,比如6就被2,3都筛过一遍
那么我们引出下面的线性筛
2.线性筛 O(n)
若有x=p1^r1*pr2^r2*...*pk^rk,p1<p2<...<pk
那么我们希望每一个数被筛掉的时候都是用它最小的质因子筛掉的
这样只会被筛掉一次
//线性筛(xxs-小学生)
int prime[233],pcnt//pcnt代表几个质数
bool not_prime[23333];
void xxs(int n)
{
not_prime[1]=true;
for(int a=2;a<=n;a++)
{
if(not_prime[a]==false)
prime[++pcnt]=a;//若a是质数,把a存下来
for(int b=1;b<=pcnt;b++)
{
int v=a*prime[b];//v表示a的质数倍
//可以理解为:要把prime[b]这个质数的a倍筛掉
if(v>n)
break;//如果v枚举到大于n了,跳出循环
not_prime[v]=true;//v设为非质数
if(a%prime[b]==0)
break;
//如果a是prime[b]的倍数,那么prime[b+1]*a也一定是prime[b]的倍数
//所以能筛掉prime[b+1]*a的最小质数不是prime[b+1],而是prime[b]
//由于想要让每个合数被最小的质数筛掉
//那么能筛掉a*prime[b]的最小质数就是prime[b]
//所以如果a%prime[b]==0,直接break
}
}
}
来源:https://www.cnblogs.com/liumengliang/p/12592466.html