談到素數判定,首先想到的兩種便是暴力判定與篩法,實現非常簡單,在此不提。
但在分解大質數時,由於數字過大,使得暴力判定會超時,篩法會超空間(可使用有技巧的限制空間篩法,但數字過大仍然過不了)
這時,我們就要引入非完美大質數判定演算法——miller rabin演算法。
下面一段引自sunshine_cfbsl部落格:
這是一種隨機性素數判定演算法,也就是說,答案可能出錯,但是可能性極小。主要內容上面已經講得很詳盡了,要注意的是:先是講兩個定理:
費馬小定理:
對於乙個質數p,取任意整數a,滿足gc
d(p,
a)=1
,則有 ap
−1≡1
(mod
p)二次探測定理: 對於0
<
x<
p ,若p是素數,則方程: x2
≡1(m
odp)
的解為: x1
=1,x
2=p−
1
a<
p ,不滿足ap
−1≡1
(mod
p),則p為合數。
所以我們可以不斷在區間[2
,p−1
] 範圍內隨機取a,並進行判定。在s次判定不為合數之後,我們就可以說這個數是質數。
但是這還不夠精確,我們可以先把p−1分解成2t
×u(u
為奇數)
的形式,然後令x[0]=au
modp
,,那麼將x[0]平方t次就是(a
u)2t
modp
的值,我們設x[i]為x[0]平方i次的值,根據二次探測定理,若x[i]等於1,則x[i−1]等於1或p-1,不滿足則p為合數。
注意以上操作中所有的形如ab
modp
的式子都要用快速冪運算,當n比較大時,形如a×
bmod
p 的式子也要使用分治的思想來計算。
這就是miller-rabin演算法的主要內容。
時間複雜度:考慮常數後為o(
slog
3n)
1、二次探測定理是為了提高miller rabin的準確性而額外增加的,在少數題中可以略去,但建議加上(不加的反例可能會在以後提到)
2、在實際操作中,可以略去陣列,用雙變數滾動賦值即可
3、快速冪與快速乘(只是這麼叫而已。。。)的實現過程要簡略而準確,以免出現不必要的失誤
詳見**。
ll modmul(ll a,ll b,ll mod)//快速乘(又名:防爆乘法(瞎起的))
//與下快速冪原理類似,不贅述
ll qpow(ll x,ll u,ll mod)//快速冪,可以在對數複雜度內完成x^u計算
//分治思想,原理可以看網上部落格
bool miller_rabin(ll n)//n為待判斷數
//分解為上述形式
srand((long long)12234336);
for(i=1;i<=50;i++)
if(x!=1)return 0;
}return 1;
}
10 9以上素數判定,Miller Rabin演算法
include include include include include define ll long long using namespace std const int s 20 隨機演算法判定次數,s越大,判錯概率越小 ll ans 給定乙個數,判斷是否是素數 常用long long大數...
MillerRabin 快速的素數概率判定法
1.作用 快速判斷單個數是否為質數 2.原理 介紹費馬小定理 對於每乙個素數p,都有ap 1 1 modp 但是不是對於每乙個有ab 1 1 modb 的b都是素數 如果存在b滿足上述規則,那麼b有1 4的機率為素數 millerrabin通過多次隨機生成b並使用以上方法進行判斷,能把錯誤的機率降到...
素數判定的一些討論(Miller Rabin演算法)
很久沒有寫部落格了。最近軍訓加開學,感覺刷題速度有降低,要補一補。回歸正題,正式進入數論階段,討論一下關於素數判定的那些事。直接根據素數的定義列舉 i 從2到 n 1 如果n i 0 n 為合數。時間複雜度 o n bool is prime int n 發現若存在 i n 使得n i 0,則必有n...