• 【刷题】BZOJ 3667 Rabin-Miller算法


    Input

    第一行:CAS,代表数据组数(不大于350),以下CAS行,每行一个数字,保证在64位长整形范围内,并且没有负数。你需要对于每个数字:第一,检验是否是质数,是质数就输出Prime 
    第二,如果不是质数,输出它最大的质因子是哪个。 

    Output

    第一行CAS(CAS<=350,代表测试数据的组数) 
    以下CAS行:每行一个数字,保证是在64位长整形范围内的正数。 
    对于每组测试数据:输出Prime,代表它是质数,或者输出它最大的质因子,代表它是和数 

    Sample Input

    6
    2
    13
    134
    8897
    1234567654321
    1000000000000

    Sample Output

    Prime
    Prime
    67
    41
    4649
    5

    HINT

    数据范围: 

    保证cas<=350,保证所有数字均在64位长整形范围内。 

    Solution

    裸Pollard Rho题

    但它不简单,反而很恶心

    不知道为什么数据那么强

    几个注意的:

    1)乘法要写快速乘,原理是a%b=a-a/b*b

    2)Miller Rabin最好优化

    3)有些版本的Pollard Rho是错的。。。被坑了好久(数学一本通)

    这东西本身有概率错误,导致调都不知道调哪里,最后是照着zhou888的代码一点一点边改边交边调的

    #include<bits/stdc++.h>
    #define ll unsigned long long
    const int Count=5;
    int base[6]={0,2,3,5,7,61};
    ll ans;
    template<typename T> inline void read(T &x)
    {
        T data=0,w=1;
        char ch=0;
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')w=-1,ch=getchar();
        while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
        x=data*w;
    }
    template<typename T> inline void write(T x,char c='')
    {
        if(x<0)putchar('-'),x=-x;
        if(x>9)write(x/10);
        putchar(x%10+'0');
        if(c!='')putchar(c);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    inline ll gcd(ll a,ll b)
    {
        return b==0?a:gcd(b,a%b);
    }
    inline ll qmul(ll a,ll b,ll n)
    {
        return (a*b-(ll)(((long double)a*b+0.5)/n)*n+n)%n;
    }
    inline ll qexp(ll a,ll b,ll n)
    {
        ll res=1;
        while(b)
        {
            if(b&1)res=qmul(res,a,n);
            a=qmul(a,a,n);
            b>>=1;
        }
        return res;
    }
    inline bool Miller_Rabin(ll N)
    {
        if(N==1||(N>3&&N%6!=1&&N%6!=5))return false;
        for(register int i=1;i<=4;++i)
            if(N==base[i])return true;
            else if(N%base[i]==0)return false;
        ll p=N-1,A,pre,k=0;
        while(!(p&1))p>>=1,++k;
        for(register int i=1;i<=Count;++i)
        {
            A=rand()%(N-1)+1;
            A=qexp(A,p,N);
            pre=A;
            for(register int j=1;j<=k;++j)
            {
                A=qmul(A,A,N);
                if(A==1&&pre!=1&&pre!=N-1)return false;
                pre=A;
            }
            if(A!=1)return false;
        }
        return true;
    }
    inline ll abs(ll x,ll y)
    {
        return y>x?y-x:x-y;
    }
    inline int Pollard_Rho(ll N,ll C)
    {
        ll k=2,x=rand()%N,y=x,d=1;
        for(register ll i=1;d==1;++i)
        {
            x=(qmul(x,x,N)+C)%N;
            d=gcd(abs(x,y),N);
            if(i==k)k<<=1ll,y=x;
        }
        return d;
    }
    inline void solve(ll N)
    {
        if(N==1)return ;
        if(Miller_Rabin(N))
        {
            chkmax(ans,N);
            return ;
        }
        ll p,c=1;
        while((p=Pollard_Rho(N,c))==N&&c<=N)c++;
        solve(p);solve(N/p);
    }
    int main()
    {
        srand(2523452);
        int T;
        read(T);
        while(T--)
        {
            ll N;
            read(N);
            ans=0;
            solve(N);
            if(ans==N)puts("Prime");
            else write(ans,'
    ');
        }
        return 0;
    }
    3667 Rabin-Miller算法
  • 相关阅读:
    jdbc入门
    mysql 各项操作流程
    python中的细小知识点罗列
    Linux之高级指令
    linux之进阶指令
    Linux之基础指令
    STL之适配器
    STL之谓词
    STL之函数对象
    STL之map容器和multimap容器
  • 原文地址:https://www.cnblogs.com/hongyj/p/8505317.html
Copyright © 2020-2023  润新知