Miller Rabin算法詳解

何爲Miller Rabin算法

首先看一下度孃的解釋(若是你懶得讀直接跳過就能夠反正也沒啥亂用:joy:)算法

Miller-Rabin算法是目前主流的基於機率的素數測試算法,在構建密碼安全體系中佔有重要的地位。經過比較各類素數測試算法和對Miller-Rabin算法進行的仔細研究,證實在計算機中構建密碼安全體系時, Miller-Rabin算法是完成素數測試的最佳選擇。經過對Miller-Rabin 算 法底層運算的優化,能夠取得較以往實現更好的性能。[1]  隨着信息技術的發展、網絡的普及和電子商務的開展, 信息安全逐步顯示出了其重要性。信息的泄密、僞造、篡改 等問題會給信息的合法擁有者帶來重大的損失。在計算機中構建密碼安全體系能夠提供4種最基本的保護信息安全的服 務:保密性、數據完整性、鑑別、抗抵賴性,從而能夠很大 程度上保護用戶的數據安全。在密碼安全體系中,公開密鑰 算法在密鑰交換、密鑰管理、身份認證等問題的處理上極其有效,所以在整個體系中佔有重要的地位。目前的公開密鑰 算法大部分基於大整數分解、有限域上的離散對數問題和橢 圓曲線上的離散對數問題,這些數學難題的構建大部分都需 要生成一種超大的素數,尤爲在經典的RSA算法中,生成的素數的質量對系統的安全性有很大的影響。目前大素數的生 成,尤爲是隨機大素數的生成主要是使用素數測試算法,本 文主要針對目前主流的Miller-Rabin 算法進行全面系統的分析 和研究,並對其實現進行了優化安全

說白了Miller Rabin算法在信息學奧賽中的應用就一句話:網絡

判斷一個數是不是素數性能

定理

Miller Rabin算法的依據是費馬小定理:測試

$$a^{p-1}\equiv 1 \pmod P$$優化

證實:ui

性質1:$p-1$個整數$a,2a,3a,...(p-1)a$中沒有一個是$p$的倍數 spa

性質2:$a,2a,3a,...(p-1)a$中沒有任何兩個同餘與模$p$的code

因此$a,2a,3a,...(p-1)a$對模$p$的同餘既不爲零,也沒有兩個同餘相同blog

所以,這$p-1$個數模$p$的同餘必定是$a,2a,3a,...(p-1)a$的某一種排列

即$a*2a*3a*...*(p-1)a \equiv {1*2*3*...*(p-1)} \pmod p$

化簡爲

$a^{p-1}*(p-1)! \equiv {p-1}! \pmod p$

根據威爾遜定理可知$(p-1)!$與$p$互質,因此同時約去$(p-1)!$

即獲得$a^{p-1}\equiv 1 \pmod P$

 

那麼是否是當一個數$p$知足任意$a$使得$a^{p-1}\equiv 1 \pmod P$成立的時候它就是素數呢?

在費馬小定理被證實後的很長一段時間裏,人們都以爲這是很顯然的,

可是終於有一天,人們給出了反例 ,推翻了這個結論

 

這是否意味着利用費馬小定理的思想去判斷素數的思想就是錯誤的呢?

答案是確定的。

可是若是咱們能夠人爲的把出錯率降到很是小呢?

好比,對於一個數,咱們有$99.99999$%的概率作出正確判斷,那這種算法不也很優越麼?

 

因而Miller Rabin算法誕生了!

 

首先介紹一下二次探測定理

若$p$爲素數,$a^{2}\equiv 1 \pmod P$,那麼$a\equiv \pm 1 \pmod P$

證實

$a^{2}\equiv 1 \pmod P$

$a^{2}-1\equiv 0 \pmod P$

$(a+1)*(a-1)\equiv 0 \pmod P$

那麼

$(a+1)\equiv 0 \pmod P$

或者

$(a-1)\equiv 0 \pmod P$

(此處可根據惟一分解定理證實)

$a\equiv \pm 1 \pmod P$

 

這個定理和素數斷定有什麼用呢?

首先,根據Miller Rabin算法的過程

假設須要判斷的數是$p$

咱們把$p-1$分解爲$2^k*t$的形式

當$p$是素數,有$a ^ {2^k * t} \equiv 1 \pmod p$

而後隨機選擇一個數$a$,計算出$a^t \pmod p$

讓其不斷的自乘,同時結合二次探測定理進行判斷

若是咱們自乘後的數$\pmod p = 1$,可是以前的數$\pmod p \not = \pm 1$

那麼這個數就是合數(違背了二次探測定理)

這樣乘$k$次,最後獲得的數就是$a^{p-1}$

那麼若是最後計算出的數不爲$1$,這個數也是合數(費馬小定理)

正確性

老祖宗告訴咱們,若$p$經過一次測試,則$p$不是素數的機率爲$25$%

那麼通過$t$輪測試,$p$不是素數的機率爲$\dfrac {1}{4^{t}}$

我習慣用$2,3,5,7,11,13,17,19$這幾個數進行判斷

在信息學範圍內出錯率爲$0$%(不帶高精)

code

注意在進行素數判斷的時候須要用到快速冪。。

這個應該比較簡單,就不細講了

#include<cstdio>
#define LL long long 
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, M, Test[10] = {2, 3, 5, 7, 11, 13, 17};
int pow(int a, int p, int mod) {
    int base = 1;
    for(; p; p >>= 1, a = (1ll * a * a) % mod) 
        if(p & 1) base = (1ll * base * a) % mod;
    return base % mod;
}
bool Query(int P) {
    if(P == 1) return 0;
    int t = P - 1, k = 0;
    while(!(t & 1)) k++, t >>= 1;
    for(int i = 0; i < 4; i++) {
        if(P == Test[i]) return 1;
        LL a = pow(Test[i], t, P), nxt = a;
        for(int j = 1; j <= k; j++) {
            nxt = (a * a) % P;
            if(nxt == 1 && a != 1 && a != P - 1) return 0;
            a = nxt;
        }
        if(a != 1) return 0;
    }
    return 1;
}
main() { 
    N = read(); M = read();    
    while(M--) puts(Query(read()) ? "Yes" : "No");
}
相關文章
相關標籤/搜索