欧拉筛基于已有的质数筛选剩下范围的合数,时间复杂度小,经常用到。
欧拉筛基本代码:
int primeArr[1000005],top;//共有1-top个质数在primeArr中
bool isPrime[5000005];
void initePrime(){
memset(isPrime,true,sizeof(isPrime));
isPrime[1] = false;
for(int i=2;i<=5000000;i++){
if(isPrime[i]){
primeArr[++top] = i;
}
for(int j=1;i*primeArr[j]<=5000000 && j<=top;j++){
isPrime[i*primeArr[j]] = false;
if(i%primeArr[j] == 0) break;
}
}
}
其中的是其保持O(n)复杂度的重要原因,下面记录一下我对欧拉筛中break的理解,方便复习。
当 ,如果不break,则下一步继续计算i*primeArr[j+1],
此时
重点来了:
此时
中的
的乘积必定大于当前的 i ,并且在i为
时,会在与
相乘时再次筛
,重复筛选了
。
而加上break可以避免重复筛选同一个数(也就是每个数就筛一次了)。
简单的例子理解:
当选中 i=8,primeArr[j] = 2,若此时不break,8*3=24在此时会被筛,8*3=2*4*3=2*12,也就是i = 12
时还会筛一次24,增加了时间复杂度,如果break则取消8*3对24的筛选,当i=12时才筛选12*2(也
就是24)。其他数的相同情况同理。
respect!