一、理解与感悟
先去掉(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;
}