數論 Miller Rabin演算法

2021-09-18 07:01:24 字數 1562 閱讀 6798

在我們需要判斷乙個數是否是素數的時候,最容易想到的就是那個熟悉的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...