一种O(n)求质数的算法

这个算法的精髓是

每个 合数 只会被自己的 最小质因子 筛 一次

看看代码理解

void pre(int n){
for(int i=2;i<=n;i++){
if(isp[i]==0){//是质数
prim[++cnt]=i;//质数
p[i]=i; //最大质因子,质数的最大质因子是它本身
}
for(int j=1;j<=cnt&&prim[j]*i<=n;j++){//把所有刚刚的质数枚举一遍
isp[prim[j] * i]=1;//不是质数
p[prim[j] * i]=p[i];//最大质因子,每个数是由最大因子筛选出
/*一个数的最大质因子是它的最大因子的最大质因子
这个break保证了合数只被最小质约数访问到。
比如40=2*20=4*10=5*8,只有i=20时,才会在prim[j]=2的时候被访问到。
当i=10时,在prim[j]=2时就已经被break了;同样的,i=8时,在prim[j]也已经break
*/
if(i%prim[j]==0)break;
}
}
}

如何理解 if(i%prim[j]==0) break;

一个数i,假设它整除prim1,即i%prim1==0

如果没有break,到下一个prim2时

prim2*i=prim1*(i/prim1*prim2) ,因为i整除prim1,且prim1<prim2

所有prim2必定不是prim2*i的最小质因子

因为每个数只会筛一次,所有复杂度O(n)