zoukankan      html  css  js  c++  java
  • Miller-Rabin算法

    Miller-Rabin算法

    欧拉定理:a,p是正整数,$ gcd(a,p)=1 $, 则 $a^{varphi(p)} equiv 1 (mod p) $ 

    费马小定理: 假如a是正整数、p是质数,且 $ gcd(a,p)=1 $,那么 $ a^{(p-1)} equiv 1(mod p)$, 即: $ a^p equiv p(mod p)$。

    对于任意素数 $p$,以及对于模p的剩余类环${1,2,...,p-1} $中的任意数 $x$,都满足$x^p equiv x(mod p) $。换句话说,$exists x$ 使得 $x^p equiv x(mod p) $不成立,$p$就不是素数。

    因此我们可以用这个小小的技巧来排除大量的合数。

    但是:p是素数是x^p=x(mod p)的充分条件,而非必要条件。

    Carmichael数:存在一类极端的合数$p$,使得所有满足$gcd(x,p)=1$的$x$,都满足$x^p equiv x(mod p) $,例如561,1105,1729。

    由于这类数的存在,使我们用费马小定理完全无法正确断定一个数是不是素数。

     二次探测定理: $ 1^2 mod p $和 $ (-1)^2 mod p $总是得到$ 1 $,称这两个数为$ 1 $的“平凡平方根”。当$ p $是素数且$ p>2 $时,不存在$ 1 mod p $的“非完全平方根”。

    证明:假设$ x,x<p$是$ 1 mod p $的平方根,于是有

    $$ x^2 equiv 1 (mod p) $$

    $$ (x+1)(x-1) equiv 0 (mod p) $$

    推出:$ p | (x+1)(x-1) $ 即 $ p | (x+1) 或 p | (x-1) $ 即 $ x=p-1 或 x=1 $ 其中 $ p-1 equiv -1 (mod p) $

    证毕。

    引理:

     假设一个奇素数$n, n>2$ ,$n-1$ 是一个偶数,可以表示为$2^s*d$的形势,$s$,$d$都是正整数且$d$是奇数。对任意在${(Z/nZ)}^*$范围内的$a$ 和 $[0,s)$范围内的$r$,必满足以下形式的一种:

    $$ a^d equiv 1 (mod n) $$

    $$ a^{2^r d} equiv -1 (mod n) $$

    证明:

    由于费马小定理:$ a^{n-1} equiv 1 (mod n ) $ 

    对$ a^{n-1} $不断取平方根,由二次探测定理,最后会得到$1$或$-1$。

    如果得到$-1$,则$2式$成立;如果从未得到$-1$,且不能继续开平方,则$1式$成立。

    证毕。

    Miller-Rabin素数测试基于上述定理的逆否:如果我们找的到一个$a$,使得对于$[0,s)$范围内的$r$,

    $$ a^d equiv 1 (mod n) $$

    $$ a^{2^r d} equiv -1 (mod n) $$

    均不满足,则$n$不是素数,这样$a$称为$n$是合数的一个凭证,否则,$a$可能是$n$是素数的强伪证。

    模板:

    考虑到爆 longlong,添加了快速加的操作。

    #include <ctime>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    typedef long long LL;
    LL ksc(LL a,LL n,LL mod){
        LL ret=0;
        for(;n;n>>=1){
            if(n&1)(ret+=a)%=mod;
            (a<<=1)%=mod;
        }
        return ret;    
    }
    LL ksm(LL a,LL n,LL mod){
        LL ret = 1;
        for(;n;n>>=1){
            if(n&1)ret=ksc(ret,a,mod);
            a=ksc(a,a,mod);
        }
        return ret;
    }
    int millerRabin(LL n){
        if(n<2 || (n!=2 && !(n&1)))return 0;
        LL d=n-1;for(;!(d&1);d>>=1);
        for(int i=0;i<20;++i){
            LL a=rand()%(n-1)+1;
            LL t=d,m=ksm(a,d,n);
            for(;t!=n-1 && m!=1 && m!=n-1;m=ksc(m,m,n),t<<=1);
            if(m!=n-1 && !(t&1)) return 0;
        }
        return 1;
    }
    int main(){
        srand(time(0));
        int T;scanf("%d",&T);
        for(LL n;T--;){
            scanf("%lld", &n);
            puts(millerRabin(n)?"Yes":"No");
        }
        return 0;
    }

    注释:

    我曾想把 millerRabin() 函数中的$ if(m!=n-1 && !(t&1)) return 0; $中的$ !(t&1) $换成$ m!=1 $, 但事实上是不行的,如果$ x $不为$ 1 $, 可是$ x^2 equiv 1 (mod 1) $,这种情况判为合数。

    例题:POJ1811

    引用:

    https://baike.baidu.com/item/%E7%B1%B3%E5%8B%92-%E6%8B%89%E5%AE%BE%E7%B4%A0%E6%80%A7%E6%A3%80%E9%AA%8C/22719763?fromtitle=Miller%20Rabin%E7%AE%97%E6%B3%95&fromid=7918305

    https://www.cnblogs.com/dalt/p/8436883.html

    http://www.matrix67.com/blog/archives/234

  • 相关阅读:
    Analysis Services features supported by SQL Server editions
    Azure DevOps to Azure AppServices
    Power BI For Competition
    Win10开机“提示语音”以及”随机播放音乐”
    Azure DevOps
    Allow Only Ajax Requests For An Action In ASP.NET Core
    Mobile CI/CD 101
    Configure SSL for SharePoint 2013
    AWS Step Function Serverless Applications
    Cordova Upload Images using File Transfer Plugin and .Net core WebAPI
  • 原文地址:https://www.cnblogs.com/hjj1871984569/p/10360729.html
Copyright © 2011-2022 走看看