代码部分 vector<bool> isPrime(currentSize, true); isPrime[0] = isPrime[1] = false; // 埃氏筛法标记非质数 for (int p = 2; p * p < currentSize; ++p) { if (isPrime[p]) { for (int i = p * p; i < currentSize; i += p) { isPrime[i] = false; } } }
一个质数的倍数一定是合数
最小质数:2 其倍数 4 6 8 10...一定都是合数。埃氏筛选法就是将0~n的数字都初始化为质数,0和1初始化为素数。从2开始筛选合数,将2的倍数设为false(合数)
然后往下继续,当isPrime[i] 为true的时候(i为质数)才执行
重点
for(int i = p * p ; i < n ; i += p )
1、从p * p
开始 而不是p + p
开始
因为p * p可以避免更多的重复
例如 2 : 从4开始 筛选出 6 8 10 12..
3:从9 开始 筛选出12 15..但是如果不从9开始 从3+3开始 则筛选出 6 9 12..会出现很多重复
2、每次加p
每次加p 意思是p的倍数 加一次就是p的两倍...从而找出质数p的到n为止的倍数
3、外层循环只用筛选 到sqrt(i)
因为 因子是成对出现的,比如 9 = 3 * 3所以如果需要判断9是否为质数,则从2开始遍历到3即可
再如果是 40 大概是 6² 所以遍历到 6和7差不多了 可以遍历到 sqrt(n) + 1
增加容错性
优点
1、相比与朴素的记除法,埃氏筛选法可以减少时间复杂度
缺点
1、无法避免的出现重复筛选,相比于欧拉筛,埃氏筛选法的时间复杂度更大
例如 p = 2 从4开始 6 8 10 12(出现了重复的12)
p = 3 从9开始 12 15 18