質數篩選 快速篩選出小於等於N的質數

2021-07-22 05:32:44 字數 1319 閱讀 1459

此方法非常的簡單:

1. 維護乙個陣列vectorprime(n + 1, true)既讓陣列中的所有數都為真,表明它是質數。

2. 對於每乙個質數,刪除它的倍數,因為質數的倍數一定是合數。讓後將陣列中對應的數改為false,這樣就可以避免遍歷他。

**如下:

int findprime(int n) 

}return res;

}

上述的篩選速度已經是很快了,但是他有乙個問題。比如合數10,在列舉2的時候我們判定了一次,在列舉5的時候我們又判定了一次。因此使得其時間複雜度比o(n)要高

與eratosthenes篩法不同的是,對於外層列舉i,無論i是質數,還是是合數,我們都會用i的倍數去篩。但在列舉的時候,我們只列舉i的質數倍。比如2i,3i,5i,…,而不去列舉4i,6i…,原因我們後面會講到。

此外,在從小到大依次列舉質數p來計算i的倍數時,我們還需要檢查i是否能夠整除p。若i能夠整除p,則停止列舉。

利用該演算法,可以保證每個合數只會被列舉到一次。我們可以證明如下命題:

假設乙個合數k=m*p1,p1為其最小的質因子。則k只會在i=m,primelist[j]=p1時被篩掉一次。

首先會在i=m,primelist[j]=p1時被篩掉是顯然的。因為p1是k的最小質因子,所以i=m的所有質因子也≥p1。於是j迴圈在列舉到primelist[j]=p1前不會break,從而一定會在i=m,primelist[j]=p1時被篩掉

其次不會在其他時候被篩掉。否則假設k在i=n, primelist[j]=p1時被篩掉了,此時有k=n*p2。由於p1是k最小的質因子,所以p2 > p1,m > n且p|n。則i=n,j列舉到primelist[j]=p1時(沒到primelist[j]=p2)就break了。所以不會有其他時候篩掉k。

同時,不列舉合數倍數的原因也在此:對於乙個合數k=m*2*3。只有在列舉到i=m*3時,才會計算到k。若我們列舉合數倍數,則可能會在i=m時,通過m*6計算到k,這樣也就造成了多次重複計算了。

綜上,eular篩法可以保證每個合數只會被列舉到一次,時間複雜度為o(n)。當n越大時,其相對於eratosthenes篩法的優勢也就越明顯。

**如下:

int findprime1(int n) 

for (int j = 1; j <= primecount; j++)

}return primecount;

}

對於兩者的時間測試來看,其差別是非常小的:

int main()

篩選法求n以內素數(質數)

設定乙個標誌陣列isprime,isprime i 的值是1就表示i是素數。開始陣列元素值全部為1劃掉k的倍數,就是把isprime 2 k isprime 3 k 置成0最後檢查isprime陣列,輸出isprime i 為1的那些i include include using namespace...

篩法求小於等於整數n的所有質數

篩法求n以下的質數最核心的是確定其倍數未消去的最大數p應該滿足的條件。要消去q的倍數,最小應該從q q考察起 因為其他跟小的倍數已經由2p,3p。p 1 p消去了 那麼消去q的倍數只需從q q開始 到n結束 滿足不等式q q n 以下是測試 include include include defin...

質數的後代 素數篩選法

題目描述 在上一季裡,曾提到過質數的孤獨,其實從另乙個角度看,無情隔膜它們的合數全是質數的後代,因為合數可以由質數相乘結合而得。如果乙個合數由兩個質數相乘而得,那麼我們就叫它是質數們的直接後代。現在,給你一系列自然數,判斷它們是否是質數的直接後代。資料規模和約定 1 t 20 2 要判斷的自然數 1...