判斷素數與尤拉篩

2021-08-23 14:31:14 字數 1869 閱讀 5993

對於乙個數,判斷是否為素數,按照性質暴力列舉每乙個,時間複雜度就是o(n),今天,不討論這個,討論一下更高效的方法。

這是我在一篇部落格看到的方法,時間複雜度為o(sqr(n)/3):

方法3)

首先看乙個關於質數分布的規律:大於等於5的質數一定和6的倍數相鄰。例如5和7,11和13,17和19等等;

證明:令x≥1,將大於等於5的自然數表示如下:

······ 6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1 ······

可以看到,不在6的倍數兩側,即6x兩側的數為6x+2,6x+3,6x+4,由於2(3x+1),3(2x+1),2(3x+2),所以它們一定不是素數,再除去6x本身,顯然,素數要出現只可能出現在6x的相鄰兩側。這裡有個題外話,關於孿生素數,有興趣的道友可以再另行了解一下,由於與我們主題無關,暫且跳過。這裡要注意的一點是,在6的倍數相鄰兩側並不是一定就是質數。

此時判斷質數可以6個為單元快進,即將方法(2)迴圈中i++步長加大為6,加快判斷速度,原因是,假如要判定的數為n,則n必定是6x-1或6x+1的形式,對於迴圈中6i-1,6i,6i+1,6i+2,6i+3,6i+4,其中如果n能被6i,6i+2,6i+4整除,則n至少得是乙個偶數,但是6x-1或6x+1的形式明顯是乙個奇數,故不成立;另外,如果n能被6i+3整除,則n至少能被3整除,但是6x能被3整除,故6x-1或6x+1(即n)不可能被3整除,故不成立。綜上,迴圈中只需要考慮6i-1和6i+1的情況,即迴圈的步長可以定為6,每次判斷迴圈變數k和k+2的情況即可,理論上講整體速度應該會是方法(2)的3倍。**如下:

bool isprime_3( int num )

公尺勒拉賓素數測試可以快速測出單個數是否為素數。

步驟:首先判斷這個數n的奇偶性

若為偶數僅有2是質數

奇數則進入測試

測試方法:

首先確定幾個基底a,範圍在[2,n-1]

因為n是奇數,所以n-1必定為偶數

則n-1可以表示為(2^s)*d

s、d分別求出來

設t為a^d模n的數,有如下幾個約定:

1.若t=-1或1時則該數n可能為質數

2.若此時t=n-1,則該數可能為質數

3.d*2>n-1時n必為合數

4.若上述皆不滿足則讓d*2,返回2

多組測試之後就能判斷是否為質數,而且錯誤率相當低!!

還有一篇部落格:說的很清楚。

#include int t,n,ans;

long long qpow(int x,int y,int mod)//快速冪

return ans;

}bool mr_prime(int a,int n)//公尺勒拉賓

long long k=qpow(a,d,n);

if(k==1) return true;//同餘1

for(int i=0;i•從

2開始列舉

i,若沒有被刪除,則加入素數表

•列舉素數表的所有素數

j,篩去

i*j,直到列舉到某個

j能整除i

時間複雜度為線性o(n)。

一般用於求乙個區間的素數。

**:long long pri[maxn];

bool ispri[maxn];

void init()

} }}

線性篩素數(尤拉篩)

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

尤拉篩 素數 基礎

求乙個數是不是素數,我們最開始用到的方法是從2開始跑到這個數的前一項,如若這些數都不能被這個數整除,那麼就稱這個數是素數 素數的概念是除了1和它本身之外不再有其他因數 除了1 我們稱這樣的數為素數。如果我們就按一般思路去實現求解這個數是不是素數,那麼會用for迴圈從2開始跑到這個數的前一項,每個數都...

尤拉篩找素數

任何合數都可以表示為多個素數的乘積,合數肯定有乙個最小的質因子,通過這個最小質因子篩掉合數,保留素數。aizu0009 求小於或等於n的素數個數 n 1,999999 include include include include using namespace std const int maxa...