一、理解与感悟
先去掉\(2\)的倍数,再去掉\(3\)的倍数,再去掉\(4\)的倍数,……依此类推,最后剩下的就是素数。
如求\(100\)以内的素数,我们只要到去掉\(sqrt(100)\)的倍数就可以了,这是因为\(10\)的\(2\)倍已经被\(2\)的倍数去掉了,\(10\)的\(3\)倍已经被\(3\)的倍数去掉了,所以到\(10\)的时候只剩下\(10\)的\(10\)倍以上的素数还存在。
同样的原因,我们在去掉\(3\)的倍数的时候,只要从\(3\)的3倍开始去掉就好了,因为\(3\)的\(2\)倍已经被\(2\)的倍数去掉了。
二、埃氏筛法
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
//埃拉筛
void get_primes(int n) {
for (int i = 2; i <= n; i++)
if (!st[i]) {
primes[cnt++] = i; //记录素数
for (int j = 2 * i; j <= n; j += i) //成倍数的标识
st[j] = true;
}
}
int main() {
//读入优化
ios::sync_with_stdio(false);
int n;
cin >> n;
get_primes(n);
cout << cnt << endl;
return 0;
}
三、欧拉筛[线性筛法]
#include <bits/stdc++.h>
using namespace std;
//欧拉筛
const int N = 1e6 + 10;
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j] * i <= n; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int main() {
int n;
cin >> n;
get_primes(n);
cout << cnt << endl;
return 0;
}