bzoj3667: Rabin-Miller算法

3667: Rabin-Miller算法

Input

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

Output

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

Miller Rabin和pollard rho模板题

卡常卡好久,最后把快速(慢速)乘改成long double才过的

#include<bits/stdc++.h>
using namespace std;
#define REP(i,st,ed) for(register int i=st,i##end=ed;i<=i##end;++i)
#define DREP(i,st,ed) for(register int i=st,i##end=ed;i>=i##end;--i)
typedef unsigned long long ll;
inline int read(){
    int x;
    char c;
    int f=1;
    while((c=getchar())!='-' && (c<'0' || c>'9'));
    if(c=='-') c=getchar(),f=-1;
    x=c^'0';
    while((c=getchar())>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0');
    return x*f;
}
inline ll readll(){
    ll x;
    char c;
    ll f=1;
    while((c=getchar())!='-' && (c<'0' || c>'9'));
    if(c=='-') c=getchar(),f=-1;
    x=c^'0';
    while((c=getchar())>='0' && c<='9') x=(x<<1ll)+(x<<3ll)+(c^'0');
    return x*f;
}
const int Times=5;
inline bool chkmax(ll &x,ll y){return (y>x)?(x=y,1):0;}
int a[4]={2,3,5,7};
ll randll(ll l,ll r){
    ll mod=(r-l+1);
    return 1ll*rand()%mod*rand()%mod+l;
}
ll work(ll x,ll y,ll mod){
    if(y>x) return x+mod-y;
    return x-y;
}
ll mul(ll x,ll y,ll mod){
    return work(x*y,(ll)((long double)x/mod*y+1e-8)*mod,mod);
}
ll ksm(ll x,ll y,ll mod){
    ll res=1;
    while(y){
        if(y&1ll) res=mul(res,x,mod);
        x=mul(x,x,mod);
        y>>=1ll;
    }
    return res;
}
bool miller_rabin(ll n){
    if(n==1 || (n>3 && n%6!=1 && n%6!=5)) return 0;
    REP(i,0,3){
        if(n==a[i]) return 1;
        if(n%a[i]==0) return 0;
    }
    ll u=n-1,cnt=0;
    while(!(u&1ll)) u>>=1ll,++cnt;
    int T=Times;
    while(T--){
        ll x=randll(2,n-1);
        ll y=ksm(x,u,n),lst;
        REP(i,1,cnt){
            lst=y,y=mul(y,y,n);
            if(y==1 && lst!=1 && lst!=n-1) return 0;
        }
        if(y!=1) return 0;
    }
    return 1;
}
ll Max;
ll gcd(ll x,ll y){
    if(!y) return x;
    return gcd(y,x%y);
}
inline ll Abs(ll x,ll y){
    if(y>x) return y-x;
    return x-y;
}
ll pollard_rho(ll n,ll c){
    ll x=rand()%n,y=x,p=1,k=2;
    for(ll i=1;p==1;++i){
        x=(mul(x,x,n)+c)%n;
        p=gcd(Abs(x,y),n);
        if(i==k) k<<=1ll,y=x;
    }
    return p;
}
void find(ll n){
    if(n==1) return;
    if(miller_rabin(n)){
        chkmax(Max,n);
        return;
    }
    ll x=n,c=0;
    while(x==n && c<=n) x=pollard_rho(n,++c);
    find(x),find(n/x);
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("pollard.in","r",stdin);
    freopen("pollard.out","w",stdout);
#endif
    srand(2523452);
    int T=read();
    while(T--){
        ll x=readll();Max=0;
        find(x);
        if(Max==x) printf("Prime\n");
        else printf("%llu\n",Max);
    }
    return 0;
}

posted @ 2018-02-26 23:55  zhou888  阅读(175)  评论(0编辑  收藏  举报