埃氏筛法(Eratosthenes Sieve)
📘 埃氏筛法(Eratosthenes Sieve)算法笔记
✨ 目标与背景
我们希望高效求出小于等于 n 的所有质数(素数)。
相比朴素判断法(每个数都除一遍),埃氏筛法大大提高了效率,时间复杂度为 O(n log log n),非常适合处理范围较大的质数筛选问题。
✅ 核心思想
筛掉合数,留下质数。
- 从 2 开始,标记其为质数。
- 把所有
2的倍数都标记为 非质数。 - 找下一个未被标记的数(如
3),认为它是质数,然后再标记它的倍数。 - 重复直到 √n。
📌 关键实现代码
vector<int> getPrimes(int n)
{
vector<bool> isPrime(n + 1, true); // 标记数组
vector<int> primes;
isPrime[0] = isPrime[1] = false; // 0 和 1 不是质数
for (int i = 2; i <= n; i++)
{
if (isPrime[i])
{
primes.push_back(i); // i 是质数
if ((long long)i * i <= n)
{
for (int j = i * i; j <= n; j += i)
{
isPrime[j] = false; // 标记 i 的倍数为合数
}
}
}
}
return primes;
}
🧠 优化细节说明
✅ for (int j = i * i; j <= n; j += i)
- 直接从
i²开始标记,因为比i²小的倍数已经被更小的质数筛掉了。 - 如
2的倍数4, 6, 8...从2²开始即可;而6 = 2*3已被2标记过。
✅ (long long)i * i <= n
- 避免
int类型乘法溢出,尤其是当n较大时。
🧪 示例:n = 10
初始: [T, T, T, T, T, T, T, T, T, T, T] // 0~10
变成: [F, F, T, T, F, T, F, T, F, F, F]
最终质数:2, 3, 5, 7
💡 时间与空间复杂度
- 时间复杂度:
O(n log log n) - 空间复杂度:
O(n)(主要用于布尔标记数组)
对比朴素方法(每个数都除一遍),效率提升巨大。可以轻松处理
n ≈ 10^6。
📌 应用场景
- 筛选范围内所有质数(如欧拉函数、区间素数)
- 快速构造素数表用于后续操作(如试除法、分解因子)
- 作为“预处理”模块在很多算法题中非常实用
📝 心得体会
- ✅ 筛法比起朴素判断法更高效、更优雅,是解决与质数有关问题的标配工具。
- ✅ 优化起始点到
i*i是算法的核心思想之一,也是避免冗余标记的关键。 - ❗ 初次实现要注意防止溢出,建议用
long long做乘法判断。
✅ 延伸学习方向
- 欧拉筛(线性筛):进一步优化到
O(n)级别。 - 区间筛法:在大范围中筛选
[L, R]区间的质数。

浙公网安备 33010602011771号