1.エリクセン画面
思考:任意の合成数は、いくつかの要因の積として表すことができ、その後、我々は、各素数を見つけることができ、それが(この番号の代わりに、合成数である)彼の倍数がマークされているだろう。我々はマーク2から始めたので2は、最も小さい素数です。時間計算量は次のとおりO(N * LOGN)
次のようにコードです。
const int maxn=1e5+10;
bool flag[maxn];
int prime[maxn];
int pri_cnt=0;
void get_prime(int n){
for(int i=2;i<=n;i++){
if(!flag[i]){
prime[++pri_cnt]=i;
for(int j=i*i;j<=n;j+=i){
flag[j]=1;
}
}
}
}
上記の場合はj=i*i
上記の考えに従って、疑いの誰かであってもよいし、初期値がj
等しくあってはならない2*i
範囲ので、それi*(2~ i-1)
で2~i-1
soから、時間外の雑草に行ったことがあるi * i
。初め
2.オイラー画面
我々はすでにエリクセンふるいふるいから知っている:思考データの量が合成数のいくつかは、より多くの素因数がマークされます繰り返した、成長して、私たちは少し最適化をした場合でも、コアがマークされているが、我々は見つけることができます。私たちは、それぞれの合成数がマークされているようなユニークな合成数は、一度だけ、時間計算量がO(N)に低減されますで標識した首相と考えることができます。
コードは次のよう:
const int maxn=1e5+10;
int v[maxn],prime[maxn];//数组v记录每个数的最小质因子
int pri_cnt=0;//pri_cnt记录质数的个数
void prime_table(int n){
for(int i=2;i<=n;i++){
if(v[i]==0){//i是质数
v[i]=i;
prime[++pri_cnt]=i;
}
for(int j=1;j<=pri_cnt;j++){
//如果(i*prime[j])有比prime[j]更小的因子,或者超出n的范围,停止循环
if(prime[j]>v[i] || prime[j]>(n/i)) break;
//prime[j]是合数i*prime[j]的最小因子
v[i*prime[j]]=prime[j];
}
}
}
prime[j]>v[i]
現在プライム示しprime[j]
乗法因子よりはi
エンゲージメントの数を表し、大きい最小素数i*prime[j]
でなければならないi
最小の素因数v[i]
電流素数ではなく、選別prime[j]
;よう= 4×3 12:たとえば、選別i=4 prime[j]=3
、12図2は、2フォー(の最小素因数である、選別されるべきであるv[4]=2
)ので、ループの外ではなく、最大画面3に、選別。
prime[j]>(n/i)
それがされているprime[j]*i>n
オーバーフローを防止するために分割することによって乗算することなく、意味する(ときに、データ時間大量の、INT破裂します)