C++ 中的 **普通筛、埃氏筛、线性筛**,它们都是求质数或判断质数的方法
普通筛、埃氏筛、线性筛,它们都是求质数或判断质数的方法,但原理和复杂度不同。
1️⃣ 普通筛(暴力判断质数)
思路:
- 对每个数
i(2 ≤ i ≤ n),判断它是否能被小于它的数整除。 - 如果不能整除,则
i是质数。
复杂度:
- 最坏情况下 O(n√n),当 n 较大时效率低。
C++ 示例:
#include <bits/stdc++.h>
using namespace std;
bool isPrime(int x) {
if (x < 2) return false;
for (int i = 2; i * i <= x; ++i)
if (x % i == 0) return false;
return true;
}
int main() {
int n;
cin >> n;
for (int i = 2; i <= n; ++i) {
if (isPrime(i)) cout << i << " ";
}
return 0;
}
2️⃣ 埃氏筛(Sieve of Eratosthenes)
思路:
- 建立长度为 n 的布尔数组
is_prime,初始都为 true。 - 从 2 开始,若
i是质数,则把i的所有倍数标记为非质数。 - 最终
is_prime[i]为 true 的就是质数。
复杂度:
- O(n log log n)
- 对 n ≤ 10⁷ 或 10⁸ 都够用。
C++ 示例:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<bool> is_prime(n+1, true);
is_prime[0] = is_prime[1] = false;
for (int i = 2; i*i <= n; ++i) {
if (is_prime[i]) {
for (int j = i*i; j <= n; j += i)
is_prime[j] = false;
}
}
for (int i = 2; i <= n; ++i) {
if (is_prime[i]) cout << i << " ";
}
return 0;
}
3️⃣ 线性筛(Linear Sieve / 欧拉筛)
特点:
- 保证每个合数只被它最小的质因子标记一次。
- 可以顺序生成质数数组
primes。 - 复杂度 O(n)(比埃氏筛更快)。
思路:
-
遍历每个数 i(2 ≤ i ≤ n)
-
如果 i 是质数,加入 primes 数组
-
遍历 primes 数组:
- 计算
i * primes[j]≤ n - 标记
i * primes[j]为非质数 - 如果 i % primes[j] == 0,则 break(保证每个数只被它最小的质因子标记一次)
- 计算
C++ 示例:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> primes;
vector<bool> is_prime(n+1, true);
for (int i = 2; i <= n; ++i) {
if (is_prime[i]) primes.push_back(i);
for (int p : primes) {
if (i * p > n) break;
is_prime[i*p] = false;
if (i % p == 0) break;
}
}
for (int p : primes) cout << p << " ";
return 0;
}
特点对比:
| 筛法 | 时间复杂度 | 优点 | 缺点 |
|---|---|---|---|
| 普通筛 | O(n√n) | 代码简单 | n 大时慢 |
| 埃氏筛 | O(n log log n) | 高效,易实现 | 不能直接获取最小质因子 |
| 线性筛 | O(n) | 高效,可求最小质因子 | 实现稍复杂 |
下面是一张“一图看懂”三种筛法的对比演示。
n = 30 时的筛法遍历轨迹(✅ 保留,❌ 划掉)
下标: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
--------------------------------------------------------------------------------------------------------------------
普通筛
i=2 ✅ → 把 4 6 8 10 12 14 16 18 20 22 24 26 28 30 全划 ❌
i=3 ✅ → 把 6 9 12 15 18 21 24 27 30 全划 ❌(6/12/18/24/30 被重复划)
i=4 已 ❌
i=5 ✅ → 把 10 15 20 25 30 全划 ❌(又重复)
……
每个合数会被它所有质因子各划一次 → 多次标记
--------------------------------------------------------------------------------------------------------------------
埃氏筛
i=2 ✅ → 从 2²=4 开始,步长 2:4 6 8 10 12 14 16 18 20 22 24 26 28 30 ❌
i=3 ✅ → 从 3²=9 开始,步长 3:9 12 15 18 21 24 27 30 ❌(12/18/24/30 虽重复,但起点高,总量减半)
i=4 已 ❌
i=5 ✅ → 从 5²=25 开始,步长 5:25 30 ❌
……
每个合数只被它的「最大质因子」划一次 → 仍可能重复,但少很多
--------------------------------------------------------------------------------------------------------------------
线性筛(欧拉筛)
外层 i 从 2→30
i=2 ✅ → 划 2×2=4 ❌
i=3 ✅ → 划 3×2=6 ❌, 3×3=9 ❌
i=4 ❌ → 划 4×2=8 ❌(4%2==0 立即 break,不再划 4×3=12)
i=5 ✅ → 划 5×2=10 ❌, 5×3=15 ❌, 5×5=25 ❌
i=6 ❌ → 划 6×2=12 ❌(6%2==0 break,不再划 6×3=18)
……
每个合数只被它最小的质因子标记一次。
--------------------------------------------------------------------------------------------------------------------
结果(30 以内质数)
✅ 保留:2 3 5 7 11 13 17 19 23 29
π(30) = 10
把上图转成记忆口诀
普通筛:见质数就狂划所有倍,重复无妨。
埃氏筛:从平方开始划,省一半。
线性筛:一遇整除就刹车,每个合数只被最小质因子划一次,真正线性。
⚠️备注:
下面把你提供的内容进一步整理成 更简洁、严谨、适合讲解或考试使用的版本,方便你在课上或材料中使用。
✅ 最大质因子(Greatest Prime Factor, GPF)
定义:
一个正整数的所有质因子(prime factors)中 最大的那个质数,称为它的最大质因子。
注意:
- 质因子只看质数。
- 重复因子不影响最大值(比如 12 的 2 出现两次也不影响答案)。
例 1:12
分解:
[
12 = 2 \times 2 \times 3
]
质因子集合 = {2, 3}
最大质因子 = 3
例 2:100
[
100 = 2 \times 2 \times 5 \times 5
]
质因子集合 = {2, 5}
最大质因子 = 5
✅ 最小质因数(Smallest Prime Factor, SPF)
定义:
一个正整数的所有质因子中 最小的那个质数,称为它的最小质因数。
例 1:12
质因子集合 = {2, 3}
最小质因数 = 2
例 2:100
质因子集合 = {2, 5}
最小质因数 = 2
🔍 二者对比总结
| 概念 | 含义 | 示例(n=100) |
|---|---|---|
| 最大质因子 | 所有质因子中最大的质数 | 5 |
| 最小质因数 | 所有质因子中最小的质数 | 2 |
- 最大质因子 = 分解中出现的最大质数
- 最小质因数 = 分解中出现的最小质数

浙公网安备 33010602011771号