Miller-Rabin,Pollard-Rho(BZOJ3667)

裸题直接做就好了。

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;

typedef long long ll;
const int p[]={2,3,5,7,11,13,17,19,23};
int T;
ll n,mx;

ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll mul(ll a,ll b,ll p) {
    ll r=a*b-(ll)((long double)a/p*b+1e-8)*p;
    return r<0?r+p:r;
}
ll qp(ll a,ll b,ll p) {
    ll r=1;
    for(;b;b>>=1,a=mul(a,a,p)) if(b&1) r=mul(r,a,p);
    return r;
}
bool chk(ll a,ll n,ll r,ll s) {
    ll x=qp(a,r,n),pre=x;
    for(int i=1;i<=s;i++,pre=x) {
        x=mul(x,x,n);
        if(x==1&&pre!=1&&pre!=n-1) return 0;
    }
    return x==1;
}
bool mr(ll n) {
    ll r=n-1,s=0;
    while(!(r&1)) r>>=1,s++;
    for(int i=0;i<9;i++) {
        if(p[i]==n) return 1;
        if(!chk(p[i],n,r,s)) return 0;
    }
    return 1;
}
ll po(ll n,ll a) {
    for(ll i=1,k=2,x=rand()%n,y=x;;i++) {
        x=(mul(x,x,n)+a)%n;
        if(gcd(n,abs(y-x))^1) return gcd(n,abs(y-x));
        if(i==k) y=x,k<<=1;
    }
}
void sol(ll n) {
    if(n==1) return;
    if(mr(n)) {mx=max(mx,n); return;}
    ll t=n;
    while(t==n) t=po(n,rand()%n);
    sol(t),sol(n/t);
}

int main() {
    srand(819733672);
    scanf("%d",&T);
    while(T--) {
        scanf("%lld",&n),mx=0,sol(n);
        if(mx==n) puts("Prime"); else printf("%lld\n",mx);
    }
    return 0;
}
posted @ 2017-01-18 15:20  Monster_Yi  阅读(202)  评论(0编辑  收藏  举报