欧拉筛是O(n)复杂度的筛素数算法,1秒内埃筛能处理1e6的数据,而1e7的数据就必须用欧拉筛了。
埃筛的基本思想是:素数的倍数一定是合数。
欧拉筛基本思想是:任何数与素数的乘积一定是合数
算法概述:
遍历[2, n]
的所有数i
,内层循环遍历已经找到的素数prime[j]
,将i * prime[j]
标记为合数。
内层循环的最后,检查如果prime[j]
是i
的最小质因子,则退出到外层循环,因为prime[j+1] * i
肯定已经被筛过了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e7 + 5;
int isPrime[MAXN]; // isPrime[i] 表示i是否素数
int prime[MAXN]; // 按顺序存素数
int cnt = 0; // 素数个数
// 找出n以内的全部(cnt个)素数
void euler(int n) {
memset(isPrime, 1, sizeof(isPrime)); // 默认全是素数
cnt = isPrime[0] = isPrime[1] = 0; // 素数个数清零,标记0和1不是素数
// 已知 [2, n] 之间的每一个数 i 与任意素数的乘积一定是合数,
// 遍历已找到全部素数 prime[j],将 i * prime[j] 标记为合数
for (int i = 2; i <= n; i++) {
if (isPrime[i]) prime[cnt++] = i; // 找到素数
for (int j = 0; j < cnt; j++) { // 遍历已找到的素数
if (i * prime[j] > n) break; // 越界跳出
isPrime[i * prime[j]] = 0; // 标记合数
// 避免重复筛除的关键代码
// 当找到i的最小质因子 prime[j] 时,退出循环
if (i % prime[j] == 0) break;
}
}
}
int main() {
int n; cin >> n;
euler(n);
// for (int i = 0; i < cnt; ++i) cout << prime[i] << endl; // 打印素数
cout << "cnt:" << cnt << endl;
return 0;
}
来源:CSDN
作者:kwansy
链接:https://blog.csdn.net/Kwansy/article/details/103586484