埃氏筛法确实大大提高了求素数的效率,但是会有很多合数被重复删去,在数据大小超过1e8的时候会支撑不住。欧拉筛法便有效先看代码:解决了这个问题,将时间复杂度降低到了O(n)。
先看代码:
int ans=0,pri[Max_n];//欧拉筛法
bool vis[Max_n];
void getpri(){
memset(vis,0,sizeof(vis));
for(int i=2;i<Max_n;i++){
if(!vis[i])pri[ans++]=i;
for(int j=0;j<ans;j++){
if(i*pri[j]>=Max_n)break;//判断是否越界
vis[i*pri[j]]=1;
if(i%pri[j]==0)break; // 保证了每个合数仅被它最小的质因数筛去
}
}
}
vis[i*pri[j]]=1:并不是要用i的倍数来消去合数,而是把 prime里面纪录的素数,升序来当做要消去合数的最小素因子。
if(i%pri[j]==0)break:保证了每个合数仅被它最小的质因数筛去。当 i是pri[j]的倍数时,i = k*pri[j],如果继续运算 j+1,i*prime[j+1] = pri[j]*k*pri[j+1],这里pri[j]是最小的素因子,当i = k*pri[j+1]时会重复,所以才跳出循环。
参考博客:https://blog.csdn.net/qq_39763472/article/details/82428602