Miller Rabin素數測試演算法模板對比

2021-07-04 22:02:06 字數 1549 閱讀 8404

昨天在usaco做了一道判斷素數的題,就想著學習一下miller_rabin素數測試演算法,在網上找到兩種模版,第一種十分簡潔,執行速度也很快,但是會判錯極少的幾個非素數;第二種比較麻煩,執行速度很慢,所以我便想找到第一種模版不能判斷的非素數特判一下,結果用了一天,電腦只找到10^8以下的,10^9內還有2個沒找到,但正確的模版執行速度太慢,我的電腦又太渣,耗不起時間了,姑且先這樣,等以後有深入理解有更好的方法再更新一下。

第一種:源自吉林大學acm模版

剛開始用的是隨機數測試,我想到以前了解過只要用2,7,61便可能判斷unsigned內的數,便做了修改,交了usaco,由於特判了5,7,11,竟然水過了,然後就愉快地去完了。。。

後來做另一道素數題,終於暴露了它的缺點,但是感覺它判斷的很快,而且只有極少的不能判斷,便先找出它的特例特判一下,經過一天的無聊列舉終於找到了。

文字對比還是自己寫來的快,網上下的用了結果記憶體爆了而且執行慢,自己寫的10s出結果(50mb的文字)。

目前只針對2,3,5,找到的特例是:4097,1048577,16777217,25326001,(960946321是乙個10^9內的特例,這個演算法列舉一次10^9,我的渣電腦都要8min左右,別說更嚴密的那個了)

bool witness(long long a,long long n) 

return d!=1;

}bool miller_rabin(long long n) ;//只用2,3,5和下面的特例判斷就能正確判斷10^8以內的所有素數,列舉一遍用時40s左右

if(n==2||n==3||n==5||n==7)

return true;

if(n==1||(n&1)==0||0==n%3||0==n%5||n==4097||n==1048577||n==16777217||n==25326001)

return false;

for(int i=0;i<3;i++)

if(witness(s[i], n))

return false;

return true;

}

第二種模版:網上大多數用的模版(模版修改自:

就算只用2,7,61判斷,也奇慢無比,列舉一次10^8要跑17min左右,但unsigned int內沒有特例

typedef unsigned long long ll;

ll modular_multi(ll x,ll y,ll mo)

ll modular_exp(ll num,ll t,ll mo)

bool miller_rabin(ll n) ;//2,7,61對unsigned int內的所有數夠用了,最小不能判斷的數為4 759 123 141;用2,3,7,61在 10^16 內唯一不能判斷的數是 46 856 248 225 981

ll a,x,y,u=n-1;

while((u&1)==0)

t++,u>>=1;

for(int i=0;i<3;i++) {

a=num[i];

x=modular_exp(a,u,n);

for(int j=0;j

Miller Rabin素數測試

公尺勒拉賓素數測試 測試大素數的原基於 如果 n 是素數 且與a 互質 那麼則有 a n 1 1 mod n 這個和費馬小定理 a n a mod n 差不多 1 因此首先可以進行快速冪取模函式 qpow 2 先將y y n 1 的偶數倍先將其右邊為0 的部分去掉 然後進行快速冪求模 3 這裡求出的...

Miller Rabin 素數測試

miller rabin 是乙個基於小費馬定理的隨機演算法。先來介紹一下費小馬定理 費馬小定理 當 p 為質數,則有當 1 leqslant a leqslant p 1 時有 a equiv 1 mod p 可能是素數 然後介紹一下素數二次測試 如果 p 是素數 x 2 equiv 1 mod p...

Miller Rabin素數測試學習筆記

好幾天前看了算導上的miller rabin素數測試演算法,今天正好總結一下,寫寫筆記。說miller rabin測試以前先說兩個比較高效的求a b n 和 ab n 的函式,這裡都是用到二進位制思想,將b拆分成二進位制,然後與a相加 相乘 a b n 例如 b 1011101那麼a b mod n...