【C++】欧拉素数筛的理解与实现
在传统的素数筛法中,我们使用了对于每一个数n,在 1~(√n) 范围内进行取模检查,这样逐一判断的复杂度为n(√n)。 但如果我们需要更快的筛法时怎么办? 于是著名的 欧拉筛 诞生了。它能将复杂度降为 O(n) 级别。 1.关键理解: 欧拉筛的原理是保证在 2~n 范围中的每一个合数都能被 唯一分解成它的最小质因数与除自己外最大的因数相乘的形式 。因此我们枚举2~n中的每一个数作为筛法中的“除自己外的最大因数”,如果它未被标记为合数,就先将它放入素数表内,再将这个最大因数与素数表中已经找到的素数作为最小质因数相乘,将得到的这些数标记为合数。最后输出得到的素数表即可。 但是我们如何保证 每个合数都被唯一分解 ? 解决方法如下: 当此时取出的素数表中的素数(即枚举的最小质因子)整除于当前枚举的合数时,我们就停止循环素数表,开始枚举下一个合数。 证明如下: 设当前枚举的最小质因子prime[i]整除于合数n时,即我们要筛掉合数 n*prime[i] ;如果我们此时不退出,继续枚举下一个素数prime[i+1],对于将要筛掉的合数 n*prime[i+1] 由于插入顺序从小到大,则 prime[i+1]>prime[i] 。由于prime[i]整除于合数n,所以必然合数 n*prime[i+1] 还可以被分解为 $$ (\frac n {prime[i]} prime[i+1])