線性篩
阿新 • • 發佈:2020-07-30
前言
每每拿到篩質數的題,就迅速敲出程式碼:
bool pd(int n) {
for(int i=2; i*i<=n; i++)
if(n%i==0) return 0;
return 1;
}
然後就獲得了TLE的大禮包……
再不學線性篩是不行了的。
埃氏篩
埃氏篩,全稱埃拉託斯特尼篩法。
列舉每一個數,每個數都有一個標記\(f\) ,如果\(f_i=true\) 代表\(i\) 不是質數,否則是質數。如果列舉到\(i\) ,\(f_i\) 為\(false\) ,那麼\(i\) 就是質數,然後把\(n\) 以內的\(i\) 的倍數的數標為\(true\) 。
- 注意,\(f\)
for(int i=2; i<=n; ++i)
{
if(!f[i])
++ans;//素數個數+1
for(int j=2; j*i<=n; ++j)
f[i*j]=true;
}
已經快得一匹了。
但這種演算法並不完美,因為有些合數會被篩兩次。
尤拉篩
尤拉篩是對埃氏篩的改進,避免了重複篩,篩完\(1\sim n\) 個數的複雜度為\(\mathcal{O}(n)\) 。
- \(prime\) 陣列用於記錄所有質數。
for(int i=2;i<=n;++i) { if(!visit[i]) prime[++ans]=i; for(int j=1;prime[j]*i<=n&&j<=ans;++j) { visit[i*prime[j]]=true; if(!(i%prime[j])) break; } }
P.S.如果不是毒瘤出題人,一般寫埃氏篩就沒啥大問題,但是如果資料大……
此人太菜不會杜教篩、min_25篩和洲閣篩/dk