质数筛
质数筛
埃氏筛
思想
- 对于一个正整数,除它本身外的所有正整数倍的数字一定都是合数
算法实现
我们利用 notprime[i] 表示一个数字是否为合数(\(0\) 为质数,\(1\) 为合数),所以:
bool notprime[maxn + 5]; // 初始均为 0:质数
for (int i = 2;i <= n;i ++)
if (notprime[i])
for (int j = 2;i * j <= n;j ++) // 枚举倍数
notprime[i * j] = true; // 筛出合数
埃氏筛的时间复杂度可以表示为 \(O(\cfrac{n}{2}+\cfrac{n}{3}+\cdots+\cfrac{n}{n})\approx O(n\ln(n))\)
线性筛
思想
在埃氏筛中,一个合数会被反复标记(合数有不同的拆分方式,如 \(12=2\times6或3 \times4或\cdots\)),这显然浪费了时间
在线性筛中,对于一个合数,我们仅在它的所有质因数中选出最小的一个 \(q\) ,此时被分解成 \(p\times q\) 的形式
算法实现
当 \(p\) 的因数中含有 \(q\) 时(p % q == 0),不再考虑 \(p\) 的其它倍数,直接跳出
bool notprime[maxn + 5]; // 初始均为 0:质数
int prime[maxn + 5],cnt = 0; // 记录质数
for (int i = 2;i <= n;i ++) {
if (!notprime[i]) prime[++ cnt] = i; // 保存质数
for (int j = 1;j <= cnt && i * prime[j] <= n;j ++) { // 枚举质因数
notprime[i * prime[j]] = true; // 标记合数
if (i % prime[j] == 0) break; // 跳出
}
}
由于所有数仅标记一次,线性筛的时间复杂度为线性复杂度 \(O(n)\)

浙公网安备 33010602011771号