1 介绍
核心思想:把2~n中的非质数打上标记(也即,筛掉),剩余的就是质数。
1.1 线性筛法/欧拉筛法
算法思路:每个非质数只会被它的最小质因子标记一次。
时间复杂度:O(N)
。
强烈推荐使用线性筛求解n以内的所有质数!!!
模板:
//输入n,以vector<int>返回n以内的所有质数
vector<int> get_primes(int n) {
vector<bool> st(n + 10, false);
vector<int> primes;
for (int i = 2; i <= n; ++i) {
if (!st[i]) primes.emplace_back(i);
for (auto prime : primes) {
if (i * prime > n) break;
st[i*prime] = true;
if (i % prime == 0) break;
}
}
return primes;
}
1.2 埃氏筛法
一般做法(也称为埃氏筛法),时间复杂度为O(N * loglogN)
int primes[N]; //存储所有的质数
int st[N]; //存储是否被排除
int cnt;
int n;
void get_primes() {
for (int i = 2; i <= n; ++i) {
if (!st[i]) {
primes[cnt++] = i;
for (int j = i + i; j <= n; j += i) {
st[j] = true;
}
}
}
//输出小于等于n的所有质数
for (int i = 0; i < cnt; ++i) cout << primes[i] << " ";
cout << endl;
return;
}
2 训练
题目1:868. 筛质数
C++代码如下,
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<bool> st(n+1, false);
vector<int> primes;
for (int i = 2; i <= n; i++) {
if (st[i] == false) primes.emplace_back(i);
for (auto prime : primes) {
if (i * prime > n) break;
st[i*prime] = true;
if (i % prime == 0) break;
}
}
cout << primes.size() << endl;
return 0;
}