線篩 尤拉篩 線性篩選素數

2021-10-03 15:24:05 字數 1562 閱讀 7882

題目描述:用線行篩篩選素數,將指定範圍的素數找出,達到o(n)的效果。

思路時間複雜度

0(n)

思路任意值必然可以被分解為:a=b1^c1*b2*c2*...

例如9=3^3,15=3*5,55=5*11

即所有的合數都可以被拆解為素數倍數的乘積。

當我們從2開始找到素數與含有素數的合數,將合數標記為非素數,每個合數都將被最小因素數標記,且只標記一次。

所以該公式雖然為雙重迴圈,但實際時間複雜度為o(n);

注意if(i%primes[j]==0)break;

當這條命令執行時,有兩種可能

1.被最小素數標記。

2.自己就是素數。

在第二種情況下往往會使合數遍歷得很大,比如i=7遍歷到49才會停止,而35就被7標記,而非2

cpp**

#include

using

namespace std;

const

int n=

1e6+10;

bool st[n]

;int primes[n]

,cnt;

//prime質數,cnt計數當前值的位置

intget_primes

(int n)}}

intmain()

以下解釋來自博主__simon_的文章尤拉線性篩素數

原理是利用了每個合數必有乙個最小素因子,每個合數僅被它的最小素因子篩去正好一次,當 i 能整除 prime[ j ],那麼i * prime[ j+

1] 這個合數肯定被 prime[j] 乘以某個數篩掉,因為 i 中有prime[j]且 i * prime[ j+

1]中也有prime[ j ]。

舉個例子:

當 i =

8,prime=

2,3,

5,7;i * prime=

16,24,

40,56;

因為8%2=

0,所以24,40,56

,可以不篩,直接break

;就如上面那句話所說的,當8能整除2時,8乘以 下乙個素數3 的值24,將會被12乘以2篩掉。

即24=8*

3=(2

*4)*

3=2*

(4*3

)=2*

12; 被12篩掉

​ 40=8

*5=(

2*4)

*5=2

*(4*

5)=2

*20; 被20篩掉

​ 56=8

*7=(

2*4)

*7=2

*(4*

7)=2

*28; 被28篩掉

這些數後面會被篩掉,即 i =

12,20,28時。所以現在就不用篩選,降低時間複雜度。

線性篩素數(尤拉篩)

尤拉篩是o n 複雜度的篩素數演算法,1秒內埃篩能處理1e6的資料,而1e7的資料就必須用尤拉篩了。埃篩的基本思想是 素數的倍數一定是合數。尤拉篩基本思想是 任何數與素數的乘積一定是合數 演算法概述 遍歷 2,n 的所有數i,內層迴圈遍歷已經找到的素數prime j 將i prime j 標記為合數...

素數線性篩法(尤拉篩)

之前寫的埃式篩法複雜度達o n log n lo gn o n logn logn o n lo gn l ogn 在大數字的時候可能複雜度還不夠理想。這種做法對於乙個合數有可能會篩了多次,導致重複做功。引入尤拉篩法能夠解決這種多次篩同乙個數字的情況,理論演算法複雜度o n o n o n 精髓在於...

素數線性篩 尤拉Euler篩

prime陣列中的素數是遞增的,當i能整除prime j 那麼i prime j 1 這個合數肯定被prime j 乘以某個數篩掉。因為i中含有prime j prime j 比prime j 1 小,即i k prime j 那麼i prime j 1 k prime j prime j 1 k ...