【タイトル出典】
https://www.acwing.com/problem/content/870/
【タイトル説明】
正の整数nが与えられたとき、1~nの中にある素数の個数を求めてください。
[入力形式]
整数nを含む合計1行。
【出力形式】
1~nの素数の個数を示す整数を含む1行。
【データ範囲】
1≦n≦10^6
【入力サンプル】
8
【出力サンプル】
4
【アルゴリズム解析】
通常の素数ふるい法、つまり、与えられた数n内のすべての数xの倍数はkx(k≧ 2) 全部ふるいにかけます。
明らかに、以下の図から、同じ数が複数の素数によって繰り返し排除される可能性があることがわかります。下図の6と12が繰り返しふるいにかけられます。
これには最適化が必要であり、オイラー篩は素数の線形篩です。原則は、各合成数がその最小の素因数によってのみ選別されるようにすることで、各合成数は 1 回だけ選別されます。
【アルゴリズムコード】
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int p[maxn];
bool st[maxn];
int cnt;
void getNum(int n) {
for(int i=2; i<=n; i++) {
if(!st[i]) p[cnt++]=i;
for(int j=0; p[j]*i<=n; j++) {
st[p[j]*i]=true;
if(i%p[j]==0) break;
}
}
}
int main() {
int n;
cin>>n;
getNum(n);
cout<<cnt<<endl;
return 0;
}
/*
in:8
out:4
*/
【参考文献】
https://zhuanlan.zhihu.com/p/494328631
https://www.acwing.com/solution/content/7950/