初學MillerRabin素數測試


前言

\(MillerRabin\)素數測試是一種很實用的素數判定方法。

它只針對單個數字進行判定,因而可以對較大的乃至於\(long\ long\)范圍內的數進行判定,而且速度也很快,是個十分優秀的算法。

前置定理

  • 費馬小定理\(a^{p-1}\equiv1(mod\ p)\)(詳見此博客:費馬小定理
  • 二次探測定理:若\(p\)為奇素數且\(x^2\equiv1(mod\ p)\),則\(x\equiv1(mod\ p)\)\(x\equiv p-1(mod\ p)\)

大致思路

假設我們要驗證\(x\)是否為素數,則我們應先找一個質數\(p\)來對其進行測試(\(p\)可以選取多個依次進行測試,只要有一個不滿足就可以確定其不是質數)。

首先,我們先判斷如果\(x=p\),則\(x\)必為質數(因為\(p\)為質數)。如果\(x\)\(p\)的倍數,則\(x\)必為合數。

然后,由於費馬小定理,我們先測試\(p^{x-1}\%x\)是否等於\(1\),如果不是,則它必然不是質數(這一步也叫作費馬測試)。

否則,我們根據二次探測定理,先用一個\(k\)記錄下\(x-1\),然后只要\(k\)為偶數就持續操作:

  • 先將\(k\)除以\(2\),然后用一個\(t\)記錄下\(p^k\%x\)的值。
  • 如果\(t\)不等於\(1\)且不等於\(p-1\),則根據二次探測定理,\(x\)非質數。
  • 如果\(t=p-1\),則無法繼續套用二次探測定理,因此直接返回\(true\)

如果一直操作到\(k\)為奇數仍然無法確定\(x\)非質數,就返回\(true\)

這一過程應該還是比較容易理解的。

代碼

class MillerRabin\\MR測試
{
    private:
        #define Pcnt 10
        Con int P[Pcnt]={2,3,5,7,11,13,19,61,2333,24251};//用於測試的質數
        I int Qpow(RI x,RI y,CI X) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}//快速冪
        I bool Check(CI x,CI p)//測試
        {
            if(!(x%P[i])||Qpow(p%x,x-1,x)^1) return false;//判斷x是否為p的倍數,然后費馬測試
            RI k=x-1,t;W(!(k&1))//持續操作直至k為奇數
            {
                if((t=Qpow(p%x,k>>=1,x))^1&&t^(x-1)) return false;//如果p^k不是1也不是-1,說明x不是質數
                if(!(t^(x-1))) return true;//如果p^k已為-1,無法用二次探測定理,因此返回true
            }return true;
        }
    public:
        I bool IsPrime(CI x)//判斷一個數是否為質數
        {
            if(x<2) return false;
            for(RI i=0;i^Pcnt;++i) {if(!(x^P[i])) return true;if(!Check(x,P[i])) return false;}//枚舉質數進行測試
            return true;
        }
}MR;


免責聲明!

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



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