1. 欧拉筛法概述
欧拉筛法(Euler's Sieve)是一种高效的素数筛选算法,能够在O(n)的时间复杂度内找出小于等于n的所有素数。与传统的埃拉托斯特尼筛法(Eratosthenes Sieve)相比,欧拉筛法通过确保每个合数只被其最小质因数筛除一次,从而达到了线性时间复杂度。
我第一次接触欧拉筛法是在解决一个需要快速生成大量素数的问题时。当时使用埃氏筛法虽然也能完成任务,但在处理大规模数据时效率明显不足。欧拉筛法不仅解决了这个问题,还让我对素数筛选有了更深的理解。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 欧拉筛法原理与实现
2.1 算法核心思想
欧拉筛法的核心在于:每个合数只被其最小质因数筛除一次。这是通过以下机制实现的:
- 维护一个素数列表
pri,存放已发现的素数 - 对于每个数i(从2到n):
- 如果i未被标记为非素数,则将其加入素数列表
- 遍历已发现的素数列表,筛除i与这些素数的乘积
关键点在于:当i能被当前素数整除时立即终止内层循环,这确保了每个合数只被其最小质因数筛除。
2.2 基础实现代码
cpp复制vector<int> pri;
bool not_prime[N];
void euler_sieve(int n) {
for(int i = 2; i <= n; i++) {
if(!not_prime[i]) {
pri.push_back(i);
}
for(int p : pri) {
if(i * p > n) break;
not_prime[i * p] = true;
if(i % p == 0) break; // 关键点
}
}
}
2.3 算法正确性证明
为什么这个算法能确保每个合数只被筛除一次?考虑任意合数x,设其最小质因数为p,那么x可以表示为x = p * m。在算法中:
- 当外层循环i = m时,内层循环会遍历到素数p
- 此时会标记i * p = x为非素数
- 由于p是x的最小质因数,必有p ≤ m的最小质因数
- 因此当i = m时,在遇到p之前不会遇
