线性筛可以做到 O(n)的复杂度筛出所有素数。
其基本原理:任何合数都能被表示成一系列素数的积。
如果你了解了 O(nlogn) 的 Eratosthenes 筛法,你就会发现其实每个数都会被多次筛到。
本算法保证每个合数只会被他的最小素因子筛到一次,所以可以做到线性复杂度。
详解见代码,这样是可以保证每个数仅被筛到一次的。
const int N = 10000;
int lp[N],primes[N],pcnt;
//lp[i]:i 的最小素因子
//pcnt:记录多少个素数
//primes:记录素数
inline void sieve(){
pcnt = 0;
memset(lp,0,sizeof(lp));
for(int i=2;i<=N;++i){
int& l = lp[i];//取地址符,修改l等价于修改lp[i]
if(l == 0)l = i,primes[pcnt++] = i;//没有最小素因子,那么他就是个素数
for(int j=0;j<pcnt&&primes[j] <= l;++j){//遍历存过的素数 当作最小素因子
int p = primes[j];//对应循环条件的p <= l 如果超出去了那么就不是最小素因子
if(i * p >= N)break;
lp[i * p] = p; //i*p的最小素因子是p
}
}
}