米勒羅賓素性測試
阿新 • • 發佈:2021-07-31
篩選法的效率很高,但是遇到大素數就無能為力了。
米勒羅賓素性測試是一個相當著名的判斷是否是素數的演算法
核心為費馬小定理:
假如 \(a\) 是整數,\(p\) 是質數,且 \(a,p\) 互質,那麼 \(a\) 的 \((p-1)\) 次方除以 \(p\)
的餘數恆等於1。
逆推一下即 \(p\)的 \(a^{p-1}%p!=1(0<a<p)\) ,它一定是合數。
如果 \(a^{p-1}%p=1(0<a<p)\) 則它可能是合數可能是素數。概率演算法的概率就在這個 a上體現。
具體過程:
1 隨機取一個 \(a\)
2 如果 它不滿足 \(a^{n-1}%n=1\)
3 則它一定是合數
4 退出
5 如果它滿足 \(a^(n-1)%n=1\)
6 則它可能是一個素數
7 回到1
米勒素數測試的合數為偽素數與Carmichael(強偽素數)
Carmichael數是非常少的,在 \(1~100000000\) 範圍內的整數中,只有 \(255\) 個Carmichael數。
為此有二次探測定理以確保該數為素數:
如果p是一個素數,\(0<x<p\) ,則方程 \(x^2≡1(mod p)\) 的解為 \(x=1,p-1\)
程式碼實現
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll q_mul(ll a,ll b,ll p) { ll ans=0; while(b) { if(b&1) ans=(ans+a)%p; a=(a<<1)%p; b>>=1; } return ans; } ll q_pow(ll a,ll b,ll p) { ll ans=1; while(b) { if(b&1) ans=q_mul(ans,a,p); a=q_mul(a,a,p); b>>=1; } return ans; } bool Miller_Rabin(ll n){ if(n==2)return true; if(n<2||!(n&1))return false; int t=2,r=0; ll m=n-1; while(m%2==0){ r++; m>>=1; } srand(100); while(t--) { ll a=rand()%(n-1)+1; ll x=q_pow(a,m,n),tmp=0; for(int i=0;i<r;i++){ tmp=q_mul(x,x,n); if(tmp==1&&x!=1&&x!=n-1)return false; x=tmp; } if(tmp!=1)return false; } return true; }
說明:
Miller-Rabin是隨機演算法
如果對這個過程重複100次,每次都沒說它是合數,那這個數是素數的概率只有(1/2)^5100