首先我們給出乙個問題:求1
~n以內
的所有質
數 最樸素的演算法是一一枚舉1~
n以內的
數,驗證
是否為素
數 一般
來說我們
驗證素數
的代價是
o(n−
−√)(
當然你也
可以用賭
徒演算法)
,這樣我
們解決這
個問題就
需要o(
nn−−
√)的代
價 那麼我們能否做的更好呢?
我們需要的就是篩法
由唯一分解定理我們知道,乙個合數總是能分解為若干個質數的乘積,因此我們產生這樣乙個想法:把所有是質數倍數的數都去掉(假如一開始我只知道2是質數),那麼剩下的就是質數了。
基於這一想法,我們創造了er
atos
then
es篩法
**如下:
memset(check, false, sizeof(check))
int tot = 0;
for (int i = 2; i < n; i++)
if (! check[i])
那麼這麼做的時間複雜度如何呢?
顯然複雜度t(
n)=∑
p≤nn
p=n∑
p≤n1
p 那麼問題就在於n以
內的質數
的倒數和
是多少
顯然這個比調和級數小(即所有數的倒數和),調和級數又比ln
小(由積
分可以知
道),所以這至多是乙個o(
nlnn
) 的演算法
具體更為精細的分析,eu
ler 在他的**裡就指出 ∑p
≤n1p
=lnl
nn因此er
atos
then
es篩法
的複雜度是o(
nlnl
nn)
注:同樣我們可以發現乙個數n不
斷地開根
號取整最
多開lo
glog
n次,我沒有發現兩者之間的聯絡,如果有人發現的話請務必告訴我eu
ler篩
法 基於這樣乙個想法:每個數隻被篩去一次,如果我能做到這一點,那麼顯然這樣的篩法就是o(
n)的
具體做法我們先看**:
memset(check, false, sizeof(check));
int tot = 0;
for (int i = 2; i <= n; i++)
}
eu
ler篩
每次都把
當前的i
與素數表
prim
e裡的素
數pj相
乘,我們
設i的最
小質因子
是p′,
那麼在p
j時,pj
都是pj
∗i這個
數的最小
質因子,
我們將它
篩去,一
旦發現p
j=p′
,也就是
pj|i
的時候,
就意味著
如果pj
再變大,
p′就將
成為pj
∗i的最
小質因子
,之後的
所有數已
經被p′
篩過一次
了,此時
我們就可
以跳出循
環了
綜上,eul
er篩的
複雜度為
o(n)
定義:定義
在正整數
集上的函
數f,對
於任意兩
個互質的
整數a,
b如果有
f(ab
)=f(
a)∗f
(b),
那麼f是
積性函式
常見積性函式:
尤拉函式
ϕ ,莫比烏斯函式μ
線性求解:
求積性函式的關鍵在於求解f(
pk) ,其它時候我們可以直接利用積性求解,而具體的f(
pk)還
是要根據
f的性質
求解
線性篩法(尤拉篩法)
嗯在剛剛 沒錯就是在幾分鐘之前 我學會了線性篩法 實在是乙個很好的篩法 正常的篩法,都會對乙個數篩多次 但是尤拉篩法不會 尤拉篩法是用它的最大因數去篩 別跟我說最小質因數,那個很難讓人理解 雖然最小質因數和最大因數是一樣的 我們假設乙個數k,它是t的最大因數 容易知道t是不唯一的 那我們要乘以乙個質...
Eratosthenes篩法(素數篩)
最一般的素數篩思想很簡單,對於不超過maxx的每個非負整數p,刪除2p,3p,4p,然後剩下的就是素數,複雜度o nlogn 因為對內層迴圈n 2 n 3 n n 小於 1 1 2 1 3 1 n ln n 1 其中 為尤拉常數 0.577218 應當注意,1不是素數哦 這樣已經不慢,但由於所有非素...
素數篩法(素數篩 線性篩)
求素數的方法在現階段可以總結為三種 這種方法最為簡單但效率太低,經過優化時間複雜度最低是o n sqrt n 輸入乙個n,輸出n以內所有素數 include intprime int n if flag 0 優化 printf d i intmain 素數篩法原理 2是素數,那麼2的所有倍數都是合數...