每日一題之 hiho1295 Eular篩法

2021-08-21 19:23:18 字數 1139 閱讀 9721

題目:

統計n以內質數個數。

思路:eular篩法

與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篩法的優勢也就越明顯。

#include 

#include

#include

using

namespace

std;

//eular 質數篩

const

int maxn = 1e6+5;

bool is_primer[maxn];

int primer_list[maxn];

int cnt;

void eular()

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

}}int main()

每日一題之 hiho1744 hohahola

描述 有一種叫作hohahola的飲料,售價是x元一瓶。小hi非常喜歡這種飲料,但是他現在身無分文。不過小hi有n張優惠券,買hohahola時每瓶最多使用一張優惠券,可以使該瓶 減少y元。y x 同時優惠券可以 小hi每 一張優惠券可以獲得z元。請你幫小hi計算通過 若干優惠券,他最多可以買多少瓶...

每日一題之 hiho1304 24點

週末,小hi和小ho都在家待著。在收拾完房間時,小ho偶然發現了一副撲克,於是兩人考慮用這副撲克來打發時間。小ho 玩點什麼好呢?小hi 兩個人啊,不如來玩24點怎麼樣,不靠運氣就靠實力的遊戲。小ho 好啊,好啊。經過若干局遊戲之後 小ho 小hi,你說如果要寫個程式來玩24點會不會很複雜啊?小hi...

每日一題之 hiho197 逆序單詞

描述 在英文中有很多逆序的單詞,比如dog和god,evil和live等等。現在給出乙份包含n個單詞的單詞表,其中每個單詞只出現一次,請你找出其中有多少對逆序單詞。輸入 第1行 1個整數,n,表示單詞數量。2 n 50,000。第2.n 1行 每行1個單詞,只包含小寫字母,每個單詞長度不超過16個字...