素數篩 記憶理解 埃氏篩和尤拉篩

2021-10-18 16:39:12 字數 1836 閱讀 2574

除了最樸素的做法外,最近新學了幾種新的判斷素數方法,記錄一下。

主要思想是如果乙個數是素數,就把他所有倍數都標記為不是素數。

#include

#include

#include

#include

using

namespace std;

const

int maxn =

1e7+10;

vector<

int> primes;

//存放素數的不定長陣列

bool prim[maxn]

;//篩除判斷

intmain()

}}vector<

int>

::iterator it;

for(it = primes.

begin()

; it != primes.

end(

); it++

) cout <<

*it << endl;

return0;

}

其中

注意點1:跳出條件優化一下,因為ii大於maxn的i,第二個for迴圈就不進行,所以沒必要。

注意點2:最早我了解的是j=2i開始,但是看優化後的應該是ii,手動模擬下發現確實不會有遺漏。當i=2,j從4開始把所有2的倍數全消掉,i=3時,j從ii=9開始把所有3的倍數全消掉,那2i呢,自然是在2時候消掉了,原因就是從2i到ii之間會被其他素數倍數給覆蓋。

再或者這樣想,ii之前肯定有i*(i-1), 如果這個i-1是素數,肯定被消過了,如果是合數,肯定會被比它小的兩個因子中小的那個給消了

尤拉篩思想的核心是要保證的是每個合數只被這個合數最小的質因子篩除,而且只篩一次,沒有重複篩除,這裡就需要用到這行**

if

(i%prime[j]==0

)break

;。

#include

#include

#include

#include

using

namespace std;

const

int maxn =

1e6+10;

int cnt=0;

//記錄已知素數數量

vector<

int> primes;

//存放素數的不定長陣列

bool judge[maxn]

;//篩除標記

intmain()

for(j=

0;j<=maxn;j++)}

vector<

int>

::iterator it;

for(it=primes.

begin()

;it!=primes.

end(

);it++

)//遍歷

return0;

}

跟埃氏篩不太一樣的是

1,埃氏篩中判斷是不是素數,不是素數就不進行下一步操作了,二尤拉篩每個數都進行操作。

2,埃氏篩一下子篩乙個數的所有倍數,尤拉篩一點點篩,舉個例子,比如i=2時候,埃氏篩一下子篩到maxn範圍內的所有2的倍數。尤拉只篩掉乙個4,所以是一點點篩的。

3,如何做到只被最小質因子篩掉呢?就是靠if(i%primes[j]==0)這一句,比如12=34=26,我們知道,12只能被26這樣篩掉而不是34,但實際過程中,2時候素數集中只有自身,篩不到12,接著就到3,也篩不到,4剛好能篩到,但我們不想讓他篩,所以用控制語句把他跳出來,再下來到6,篩掉。

還是不太懂,感覺沒透,做題還是得。加油把!現在去玩會遊戲hh,

埃氏篩 尤拉篩

對於1 n範圍內素數的查詢,我們常用的二重迴圈暴力演算法的複雜度是o n2 如果利用開根縮小範圍的時間複雜度也無非是在o n nn sqrt n nn 而,這些演算法對於n在105以內都是可以接受的,但是如果需要更大範圍的素數表,這些演算法將顯得力不從心。下面將介紹更加高效的演算法。埃氏篩也叫素數篩...

素數篩法 埃氏篩及尤拉篩

在做題中會經常遇到有關素數的問題,整理一下學過的兩種素數篩法。時間複雜度 o nloglogn 我們知道乙個素數的倍數肯定是乙個合數,乙個合數可以由多個素數相乘得到,所以可以從2開始把2的倍數篩一遍,找到下個素數在篩一遍。篩完後素數的倍數都被篩掉了,剩下的就是素數。如下 const int n 1e...

埃氏篩 線性 尤拉 篩

埃氏篩 簡單,暴力。int isprime 50000 void getlist int size 看似簡單,但不真搞明白這個,無法學會線性 尤拉 篩。關鍵在於如何去做的合數,用了兩個引數,乙個是質數,即 prime i 另乙個是質數的倍數,即 j 相乘得到合數。線性篩 埃氏篩的改良版,使乙個合數只...