Miller-Rabin算法


  Miller-Rabin算法用於檢測一個數n是否是素數。其時間復雜度上界為O(klog2(n)),其中k為檢測的輪數。增大k可以提高Miller-Rabin算法的准確度。

  要檢測一個數是否為素數,簡單的算法有兩種,第一種是對2~√n之間的數,檢查其是否是n的因子,其時間復雜度為O(√n)。第二種就是打表法,利用歐拉篩可以在O(N)的時空復雜度內獲取1~N之間的所有素數並存儲。無論是哪種情況,對於超大的n,都要消耗可怕的時間來進行判斷,譬如取n為1e18,這樣兩種算法在現代計算機上都是無法結束的(后者會直接內存不足)。

  數論中的費馬小定理中指出,對於任意素數p,以及對於模p的剩余類環{1,2,...,p-1}中的任意數x,都滿足x^p=x(mod p)。因此我們可以用這個小小的技巧來排除大量的合數。譬如對於素數5,我們發現2^5(mod 5)=2,而對於6,有2^6(mod 6)=4。

  但是費馬小定理中p是素數是x^p=x(mod p)的充分條件,而非必要條件,比如4^6=4(mod 6),但我們不能說6是素數。因此我們需要從模p的剩余類環中選取更多的數進行測試,以增強結果的可信度,只要存在一個數x不滿足x^p=x(mod p),那么p就絕不可能是素數。但是還是存在一類極端的合數p,使得對於任意1,..,p-1中的x都滿足x^p=x(mod p),這類合數稱為Carmichael數,一個例子就是561。由於這類數的存在,使得我們用費馬小定理完全無法正確斷定一個數為素數還是合數。

  而Miller-Rabin算法的出世使得相當一類的滿足費馬小定理的合數無法通過素數測試。Miller-Rabin算法基於一個事實,若x^2=1(mod p),那么若p是素數,則(x-1)(x+1)=0(mod p),除非p為2,否則(x-1)與(x+1)在模p的性質下是不相等的,無論p是否為2,都可以保證有(x-1)=0(mod p)或者(x+1)=0(mod p)(因為模p剩余類環是整環),即x=1或x=p-1。因此我們可以在p通過數x的費馬測試后,即x^p=p(mod p),也可以寫作x^(p-1)=1(mod p),若p-1是偶數,那么可以繼續通過x^((p-1)/2)是否等於1或(p-1)來進行測試。如果測試通過還可以繼續判斷是否滿足x^2k=1(mod p),從而繼續進行判斷。只要一環判斷不通過,那么就保證p是合數。

  看一下我們方才提過的Carmichael數561,進行Miller-Rabin測試:

  2^560=1(mod 561)  滿足

  2^280=1(mod 561)  滿足

  2^140=67(mod 561)   不滿足
  下面給出我個人使用的MR算法的模板:

mr(p)
    if(p == 2 || p == 3 || p == 5 || p == 7)
        return true
    return mr0(2, p) && mr0(3, p) && mr0(5, p) && mr0(7, p)

mr0(x, p)
    if (x^(p-1)) % p != 1
        return false
    k = p - 1
    while k % 2 == 0
        k = k / 2
        t = x^k
        if(t != 1 && t != p - 1)
            return false
        if(t == p - 1)
            return true
    return true

    由於mr0中的冪運算可以利用快速冪乘法的技術來實現,因此一次冪運算的時間復雜度為O(log2n),而while循環最多執行log2(p)次,每次循環執行一次冪乘運算,故總的時間復雜度為O((log2p)^2)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM