【刷题】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='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(c!='\0')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,'\n');
    }
    return 0;
}
3667 Rabin-Miller算法

 

posted @ 2018-03-04 17:45  HYJ_cnyali  阅读(207)  评论(0编辑  收藏  举报