• POJ1811- Prime Test(Miller–Rabin+Pollard's rho)


    题目大意

    给你一个非常大的整数,判断它是不是素数,如果不是则输出它的最小的因子

    题解

    看了一整天《初等数论及其应用》相关部分,终于把Miller–Rabin和Pollard's rho这两个算法看懂了O(∩_∩)O~~

    Miller–Rabin主要用到了费马小定理,即:设p是一个素数,a是一个正整数且p不整除a,则ap-1≡1(mod p).若x=b(n-1)/2,x2=bn-1≡1(mod n),如果n是一个素数,则x≡1(mod n)或者x≡-1(mod n).因此,一旦我们有bn-1≡1(mod n),则可以检验b(n-1)/2≡±1(mod n)是否成立.若该同余式不成立,则可知n合数.因此我们可以令n-1=2tu,(t>=1且 u是奇数),bn-1≡(bu)^2t(mod n),通过先计算bu,然后对结果连续平方t次来计算bn-1(mod n),如果通过这种这种测试,则称n通过了以b为基数的米勒检验,我们可以多选取几个b,如果都通过了检测,则n有很大的机率是素数~~~

     

    Pollard's rho 主要是基于Floyd's cycle-finding algorithm,算导上图非常形象~~讲得也挺好~~~我就不造轮子了。。。。我选取的函数式f(x)=x^2+1,每次都跑了1000多ms%>_<%。。。

    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    typedef unsigned long long LL;
    LL min(LL a,LL b)
    {
        return a<b?a:b;
    }
    LL gcd(LL a,LL b)
    {
        return b==0?a:gcd(b,a%b);
    }
    LL mult_mod(LL a,LL b,LL mod)
    {
        LL ans=0;
        while(b)
        {
            if(b&1)
                ans=(ans+a)%mod;
            a=(a<<1)%mod;
            b>>=1;
        }
        return ans;
    }
    LL pow_mod(LL a,LL b,LL mod)
    {
        LL d=1;
        a%=mod;
        while(b)
        {
            if(b&1)
                d=mult_mod(d,a,mod);
            a=mult_mod(a,a,mod);
            b>>=1;
        }
        return d%mod;
    }
    bool witness(LL a,LL n)
    {
        LL u=n-1,t=0;
        while((u&1)==0)
        {
            u>>=1;
            t++;
        }
        LL x,x0=pow_mod(a,u,n);
        for(LL i=1; i<=t; i++)
        {
            x=mult_mod(x0,x0,n);
            if(x==1&&x0!=1&&x0!=(n-1))
                return true;
            x0=x;
        }
        if(x!=1)
            return true;
        return false;
    }
    bool miller_rabin(LL n)
    {
        if(n==2) return true;
        if(n<2||!(n&1)) return false;
        for(int j=1; j<=8; j++)
        {
            LL a=rand()%(n-1)+1;
            if(witness(a,n))
                return false;
        }
        return true;
    }
    LL pollard_rho(LL n)
    {
        LL i=1,x=2,y=2,k=2,d;
        while(true)
        {
            i++;
            x=(mult_mod(x,x,n)+1)%n;
            d=gcd(y-x,n);
            if(d!=1&&d!=n)
                return d;
            if(x==y) return n;
            if(i==k)
            {
                y=x;
                k<<=1;
            }
        }
    }
    LL find_minfac(LL n)
    {
        if(miller_rabin(n)||n<=1)
            return n;
        LL p=pollard_rho(n);
        LL q=min(find_minfac(p),find_minfac(n/p));
        return q;
    }
    int main()
    {
        int T;
        LL n;
        scanf("%d",&T);
        srand(time(NULL));
        while(T--)
        {
            scanf("%I64u",&n);
            if(n>2&&n%2==0) printf("2
    ");
            else if(n==2||miller_rabin(n))
                printf("Prime
    ");
            else
                printf("%I64u
    ",find_minfac(n));
        }
        return 0;
    }

     

     

  • 相关阅读:
    SCCM2012 R2实战系列之四:初始化配置
    SCCM 2012 R2实战系列之一:SQL安装
    hdu 1242(bfs)
    hdu 1728(bfs)
    hdu 1253(bfs)
    hdu 3661
    hdu 1072(bfs)
    AC模版
    hdu 1010(dfs)
    poj 3628(01_page, dfs)
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3238856.html
Copyright © 2020-2023  润新知