0%

质数筛法

本文包括埃氏筛和线性筛。

埃氏筛

Θ(nloglogn)\Theta(n\log \log n)

复杂度证明需要复变函数知识,从略。

1
2
3
4
5
6
7
8
9
void prime()
{
for (int i = 2; i <= N; i++) {
if (isp[i]) continue;
pri[++cnt] = i;
for (int j = i + i; j <= N; j += i)
isp[j] = 1;
}
}

线性筛

Θ(n)\Theta(n)

保证了每个合数只被最小质因数筛除一次。

1
2
3
4
5
6
7
8
9
10
11
void prime()
{
for (int i = 2; i <= N; i++) {
if (!isp[i])
pri[++cnt] = i;
for (int j = 1; pri[j] * i <= N; j++) {
isp[pri[j] * i] = 1;
if (i % pri[j] == 0) break; // 关键代码
}
}
}

对关键代码的正确性进行证明。设第二层循环枚举到 prij0pri_{j0} 时,满足 if 的条件。若此时不终止循环,则对于后续枚举到的 prij1pri_{j1},均有等式

prij1i=iprij0n(prij0nprij1)pri_{j1} \cdot i=\frac{i}{pri_{j0}^n}\cdot (pri_{j0}^n\cdot pri_{j_1})

此时则造成了对同一合数的重复枚举。又因为对等式右边相乘的两数, gcd(iprij0n,prij0nprij1)=1\gcd(\frac{i}{pri_{j0}^n},pri_{j0}^n\cdot pri_{j_1})=1,所以这两个数的组合必然能在 if 跳出循环前出现,得证。