筛素数
筛素数
主要就是埃氏筛,欧拉筛(线性筛)。
1. 埃氏筛
思路:
首先知道 \(2\) 是质数,然后划掉所有 \(2\) 的倍数,找到第一个没划掉的,它也是素数,再将它的倍数划掉,以此类推。
比较好理解。
有个小优化,考虑筛 \(x\) 的倍数时 \(x^2\) 以前都被筛过了,所以可以直接从 \(x^2\) 开始枚举,复杂度 \(O(n\log\log n)\)
CODE
for(int i=2;i<=R;i++){
if(!ntp[i]){
pri[++ttp_]=i;
for(int j=i;j<=R/i;j++) ntp[i*j]=1; //不要用 j=i*i ,会越界
}
}
欧拉筛(线性筛)
其实它可以筛所有的积性函数,我不会就是了
我们发现埃氏筛优化后还有重复筛的,考虑能不能一个数只被筛一次。
我们让一个数只被它的最小质因子筛掉,只要改变一下它筛的实现。
具体的,对于一个数(无论质数和合数)都对 \(1\) 到其最小质因数内所有质数进行扩展(也就是筛掉它们的积)。
CODE
for(int i=2;i<=n;i++){
if(!ntp[i]) pri[++ttp_]=i;
for(int j=1;j<=ttp_;j++){
if(i*pri[j]>=R) break;
ntp[i*pri[j]]=1;
if(!(i%pri[j])) break; // 只扩展到最小质因数
}
}
为什么要扩展到其最小质因数:
设现在这个数 \(i=pt\),其中 \(p\) 是其最小质因数。
当我们筛 \(x*pt\)(\(x\) 是目前的质数 \(pri_j\)),若 \(x>p\),则这个数可以被 \(p\) 和 \(xt\) 筛掉,就会造成重筛,所以到此为止。
为什么不会漏筛:
因为一个和数一定可以分成 \(x*pt\),其中 \(x<p\) 且为质数,\(t\) 为合数或 \(1\) ,所以这个合数一定会在筛 \(pt\) 时被筛掉。
——————————————————————————————————————————————————————————————————————————————————————————————————————————
本文来自博客园,作者:xrlong,转载请注明原文链接:https://www.cnblogs.com/xrlong/articles/17606502.html