篩法 個人對篩法的理解

2021-07-09 20:21:15 字數 2289 閱讀 3896

首先我們給出乙個問題:求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的所有倍數都是合數...