篩法求素數

2022-07-17 18:12:09 字數 1166 閱讀 3482

線性篩法求素數

顧名思義,其時間複雜度為o(n)。

1 #include2

using

namespace

std;

3const

long maxp = 200000

; 4

long prime[maxp] = ,num_prime = 0

; 5

int isnotprime[maxp] = ;

6int

main() 7

18}

19return

0;

20 }

if( !(i %prime[j])) 

break;

為什麼這裡要break?先可以得出乙個結論,此時的prime[j]為(i*prime[j])的最小質因數。現設x=p1*a為合數,且p1為其最小的質因子,a為質數或合數,若為質數,則設a=1*p`(a`=1),否則設a=a`*p`,p`為質數(因為任意乙個合數都可以表示成乙個質數和另乙個數的乘積)。則x=(p1*a`)*p`=p1*(a`*p`),且可以知道p1*a`<=p`*a`,即合數(p1*a`)小於合數(p`*a`),且p1<=p`,故得出結論,即比乙個合數數大的質數和該合數的乘積可用乙個更大的合數和比其小的質數相乘得到。

在上面實現**中,i在1~maxp間迴圈,在i=p1*a時,若滿足 !(i % prime[j])而不break的話,有可能在後面遇到乙個prime[k],使得某個數x`=p1`*a`*prime[k],在之後i=(a`*prime[k])時,還會再和p1`相乘重新進行isnotprime[i * prime[j]] = 1;  賦值,這樣就造成了重複賦值,降低了效率,如果break了,則不會出現這樣的情況。

考慮完上面的問題,還有個問題需要考慮,即省去的i*prime[k]在後來的過程中一定會再出現從而使得將isnotprime[i * prime[k]]賦值為1麼?答案是肯定的,因為上面提到了任意乙個合數都可以表示成乙個質數和另乙個數的乘積,所以任意乙個數總能表示成其最小質因子與另乙個數相稱的形式,因為我們列舉了所有可能的i,故「另乙個數」的所有可能性我們都有考慮,所以,只要我們找到其最小質因子則就不會漏掉任意乙個數。

1

void

sieve()213

return

;14 }

篩法求素數 線性篩法求素數

2021年更新版 篩法求素數 線性篩法求素數 要理解篩法求素數首先要知道乙個定理,整數唯一分解定理 任意大於等於2的正整數都有且只有一種方式寫出其質因子的乘積表示式。a p1p2p3p4 pn pi是素數且pi pj eg 2 2 4 22 12 223 36 2233 也就是說任意乙個合數都能分成...

素數篩法求素數

素數篩類似於打表標記,預先處理掉非素數的數,即素數的倍數 任意非素數都可以由幾個素數相乘得到 於是效率比暴力求解快得多。埃氏篩法的效率為o n loglog n 簡單易懂,但是會重複標記,比如當i為2時,6會被標記掉,然而當i為3時,6又會被重複標記,這樣的重複訪問加大了時間複雜度,於是有了尤拉篩。...

篩法求素數

素數篩法就是每次把已知的素數的倍數曬去,篩掉前sqrt n 中素數的倍數就可以了 先把n個自然數按次序排列起來。1不是質數,也不是合數,要划去。第二個數2是質數留下來,而把2後面所有能被2整除的數都劃去。2後面第乙個沒劃去的數是3,把3留下,再把3後面所有能被3整除的數都劃去。3後面第乙個沒劃去的數...