线性筛质数
埃筛
for(int i=2; i<=n; i++)
{
if(!del[i])
{
prim[++tot]=i;
for(int j=i; i*j<=n; j++) del[i*j]=1;
}
}
时间复杂度 \(O(n \log \log n)\)
欧筛
for(int i=2; i<=n; i++)
{
if(!del[i]) prim[++tot]=i;
for(int j=1; j<=tot&&prim[j]*i<=n; j++)
{
del[i*prim[j]]=1;
if(i%prim[j]==0) break;
}
}
if(i%prim[j]) break; 是最关键的一句话
是用来防止重复的,作用如下:
如果 \(prime_x\) 是 \(y\) 的最小质因数,那就说 \(y\) 是符合关于 \(prime_x\) 的“筛条件”的
\(j\) 循环到 \(i \mod prime_j\) 就恰好需要停止的理由是:
- \(i\) 的最小质因数肯定是 \(prime_j\)
如果 \(i\) 的最小质因数是 \(prime_s\) ,那么 \(prime_s\) 更早被枚举到(因为我们从小到大枚举质数),当时就会 break
既然 \(i\) 的最小质因数是 \(prime_j\) ,那么 \(i \times prime_j\) 的最小质因数也是 \(prime_j\) 。所以,\(i*prime_j\) 是符合关于 \(prime_j\) “筛条件”的。
-
设 \(prime_s\) 是 \(\leq i \times prime_j\) 的质数, \(i \times prime_s\) 的最小质因数是 \(prime_s\)
如果是它的最小质因数是更小的质数 \(prime_t\),那么当然\(prime_t\) 更早被枚举到,当时就要
break这说明 \(j\) 之前(用 \(i \times prime_s\) 的方式去筛合数,使用的是最小质因数)都符合是符合关于 \(prime_s\) 的“筛条件”。
-
设 \(prime_l\) 是 \(\geq i \times prime_j\) 的质数, \(i \times prime_l\) 的最小质因数是 \(prime_j\)
因为 \(i\) 的最小质因数是 \(prime_j\),所以 \(i \times prime_l\) 也含有 \(prime_j\) 这个因数,所以其最小质因数也是 \(prime_j\)(新的质因数 \(prime_l\) 太大了
这说明,如果 \(j\) 继续递增(将以 \(i \times prime_l\) 的方式去筛合数,没有使用最小质因数),是不符合“筛条件”的。
经过这个优化,欧筛的时间复杂度是 \(O(n)\) 的

浙公网安备 33010602011771号