在我們需要判斷乙個數是否是素數的時候,最容易想到的就是那個熟悉的o(√n)的演算法。那個演算法非常的簡單易懂,但如果我們仔細想想,當n這個數字很大的時候,這個演算法其實是不夠用的,時間複雜度會相對比較高。
怎麼解決呢?我們先來了解一下「費馬小定理」。假設我們有乙個素數p,且另乙個數a和p互素,就可以得到ap-1≡1(mod p)。這個定理很巧妙啊,有人就想了,能不能通過費馬小定理來判斷乙個數是否是素數呢?也就是說,當我們判斷乙個數p是否是素數時,只需要判斷ap-1≡1(mod p)是否成立即可。這裡的a因為是任意數,乾脆就讓它等於2,那麼判斷乙個數p是否是素數就轉化成了判斷2p-1≡1(mod p)是否成立。乍一看,這好像沒什麼問題。當這個式子不成立時,p一定是乙個合數,這沒毛病;但是當式子成立的時候p就一定是素數嗎?我們舉個反例。當p = 341時,2340≡1(mod 341)成立,然而很不巧,341 = 11 * 31是乙個純正的合數。這就是數學中所說的,對於所有的a都存在對應的偽素數。(ps:這個問題並不能完全通過改變基數解決)
那我們該怎麼辦呢?其實很簡單,只需要進行「二次探測」把偽素數揪出來就ok了。這可不是亂改,是有依據的:當p為素數時,方程x2≡1(mod p)有兩個根 x = 1 和 x = p - 1。這兩個根被我們賦予了乙個奇怪的名字:平凡平方根。那麼,判斷乙個數p是否是素數這個問題就又被我們轉化,變成了判斷在模p意義下是否存在1的非平凡平方根,若存在則p為合數,反之則為素數。這一測試被我們「親切地」稱為「miller - rabin測試」。
具體操作步驟如下:
①選取多個基數a進行測試;
②尋找模p為1的非平凡平方根;令p - 1 = 2t*u(t >= 1, u為奇數),ap-1 = a2t*u = a2t ,先算出x=au (mod p),再把 x 平方 t 次,每次模上 p,這樣我們就得到了乙個長度為 t + 1 的序列。我們希望這個序列以 1 結尾。若中間某一項為 1,則這一項的前一項必須為 1 或 n - 1,否則p就是合數。
在miller - rabin測試中進行s次測試,這並不代表這項測試是簡單地驗證費馬小定理,它大大降低了出錯的概率,研究表明,miller - rabin測試的出錯概率至多為 2-s 這可以說是非常小了。所以不用擔心它的準確度和嚴謹性。
**如下:
#includeusing namespace std;
int pow(long long a, long long b, long long n)
a = a * a % n;
b >>= 1;
} return ans;
}bool judge(long long n, long long a)
long long x = pow(a, t, n);
for (int i = 1; i <= u; i++)
if (x != 1) return true;
return false;
}bool miller(long long n, int s)
return true;
}int main()
else cout << "no" << endl;
} return 0;
}
Miller Rabin演算法詳解
目錄 基本引理 1,費馬定理 2,二次探測定理 作用 證明 實現 目錄 基本引理 1,費馬定理 2,二次探測定理 費馬定理的證明鏈結 二次探測定理的證明鏈結 有效的檢測大整數是否為素數。由費馬定理,可以排除大部分非素數的情況 滿足費馬定理是素數的必要條件 給出乙個奇素數n,顯然n 1為乙個偶數,存在...
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...
素數判定 Miller Rabin 演算法
談到素數判定,首先想到的兩種便是暴力判定與篩法,實現非常簡單,在此不提。但在分解大質數時,由於數字過大,使得暴力判定會超時,篩法會超空間 可使用有技巧的限制空間篩法,但數字過大仍然過不了 這時,我們就要引入非完美大質數判定演算法 miller rabin演算法。下面一段引自sunshine cfbs...