miller rabin演算法是乙個隨機化素數測試演算法,作用是判斷乙個數是否是素數,且只要你臉不黑以及常數不要巨大一般來講都比\(o(\sqrt n)\)的樸素做法更快。
miller rabin主要基於費馬小定理:
\[a ^ \equiv 1 (mod p)\]其中\(p\)是質數。
於是就有閒得沒事幹的一群科學家們想,這個問題的逆命題是否成立呢?
逆命題:若對於任意\(a\),\(a ^ \equiv 1 (mod p)\)都成立,那麼\(p\)是質數。在很長一段時間裡,所有人幾乎都以為它是成立的。然鵝你們手玩乙個\(a=8, p = 9\)試試
是的,這個東西被搞出了反例。不過幸運的是,用這個辦法測試通過的數,還是有很大概率是質數的。
這好辦,我們多搞幾次不就可以當做它就是質數了嗎!臉黑另說
首先我們還得了解乙個叫二次探測定理的東西:
\[若p是質數,且x^2 \equiv 1 (mod p), 則有x \equiv ±1 (mod p)\]證明很簡單,第乙個式子右邊丟過去平方差即可。由於p是質數,所以它肯定不是\((x-1)和(x+1)\)湊起來的,故兩個裡面總有乙個是\(p\)的倍數。
而且很容易腦補的是,這個東西的逆命題是成立的。(劃重點)
所以根據這兩個定理,我們設計一波演算法:
假設我們要判斷的數是\(p\),那麼\(2\)特判一波,剩下的質數肯定是奇數。
所以\(p-1\)一定是乙個偶數。然後就好辦啦!
我們把\(p-1\)分解成\(2^k * t\),當\(p\)是素數時,根據費馬小定理有\[a ^ \equiv 1 (mod p)\]
那麼我們隨機出乙個\(a\),然後求出\(a^t\),再不斷乘上\(a\),每次進行二次探測,邊乘邊模,若乘之前不符合二次探測,而乘之後符合,那麼p是合數,不符合題意。自乘\(k\)次,最後得到\(a^\),如果模\(p\)不等於1,則也是合數。(不符合費馬小定理)
老祖宗告訴我們(這個我也不會證),每一次通過測試的數不是質數的概率為\(\frac\),則測試\(k\)次,錯誤的概率為\(\frac\),\(k>6\)的時候基本就血賺了。
#includeusing namespace std;
typedef long long ll;
int c[23] = ;
int n, m;
inline ll read()
while (isdigit(c))
return cnt * f;
}inline ll ksm(ll a, ll b, ll c)
return ans % c;
}bool miller_rabin(int p)
cur = nxt;
}if (cur != 1) f = 0;
if (!f) break;
}return f;
}int main()
return 0;
}
Miller Rabin演算法詳解
目錄 基本引理 1,費馬定理 2,二次探測定理 作用 證明 實現 目錄 基本引理 1,費馬定理 2,二次探測定理 費馬定理的證明鏈結 二次探測定理的證明鏈結 有效的檢測大整數是否為素數。由費馬定理,可以排除大部分非素數的情況 滿足費馬定理是素數的必要條件 給出乙個奇素數n,顯然n 1為乙個偶數,存在...
數論 Miller Rabin演算法
在我們需要判斷乙個數是否是素數的時候,最容易想到的就是那個熟悉的o n 的演算法。那個演算法非常的簡單易懂,但如果我們仔細想想,當n這個數字很大的時候,這個演算法其實是不夠用的,時間複雜度會相對比較高。怎麼解決呢?我們先來了解一下 費馬小定理 假設我們有乙個素數p,且另乙個數a和p互素,就可以得到a...
Miller Rabin演算法詳解
原文 判斷乙個數是否是素數 如果p是素數,且整數a不是p的倍數有 a equiv 1 pmod p 費馬定理只是n是素數的必要條件。即費馬定理不成立,n一定是合數 費馬定理成立,n可能是素數。性質 1 p 1 個整數 a,2a,3a,p 1 a 中沒有乙個是 p 的倍數 性質 2 a,2a,3a,p...