POJ - 1811 Prime Test

pallord-rho模板

传送门

不能srand,不能srand,不能srand

为此RE了40min

//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=1e5+7;
typedef long long LL;
using namespace std;
int T;
LL x,p[N]; 

template<typename T> void read(T &x) {
    T f=1; x=0; char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}

LL ksc(LL a,LL b,LL mod) {
    LL base=a%mod,res=0;
    while(b) {
        if(b&1) res=(res+base)%mod;
        base=(base+base)%mod;
        b>>=1;
    } 
    return res;
}

LL ksm(LL a,LL b,LL mod) {
    LL base=a,res=1;
    while(b) {
        if(b&1) res=ksc(res,base,mod);
        base=ksc(base,base,mod);
        b>>=1;
    }
    return res;
}

int miller_rabin(LL n) {
    LL u=n-1;
    int k=0;
    if(n==2||n==3||n==5||n==7||n==11) return 1; 
    if(!(n%2)||!(n%3)||!(n%5)||!(n%7)||!(n%11)) return 0;
    while(!(u&1)) {
        u>>=1; k++;
    }
    for(int i=1;i<=20;i++) {
        LL x=rand()%(n-2)+2;
        LL tp=ksm(x,u,n);
        for(int j=1;j<=k;j++) {
            LL tpp=ksc(tp,tp,n);
            if(tpp==1&&tp!=1&&tp!=n-1) return 0;
            tp=tpp;
        }
        if(tp!=1) return 0;
    }
    return 1;
} 

LL gcd(LL a,LL b) {return (!b)?a:gcd(b,a%b);}

LL pallord_rho(LL n,int c) {
    LL x=rand()%n,y=x;
    int k=2,i=1;
    for(;;) {
        i++;
        x=(ksc(x,x,n)+c)%n;
        LL tp=gcd((x-y+n)%n,n);
        if(tp>1&&tp<n) return tp;
        if(x==y) return n; 
        if(i==k) y=x,k+=k;
    }
}

void find(LL n) {
    if(miller_rabin(n)) {
        p[++p[0]]=n;
        return ;
    } 
    LL p=n;
    for(int c=13;;c++) {
        p=pallord_rho(n,c);
        if(p>1&&p<n) break;
    }
    find(p); find(n/p);
}

int main() {
    read(T);
    while(T--) {
        p[0]=0;
        read(x);
        if(x==1||miller_rabin(x)) puts("Prime");
        else {    
            find(x);
            LL ans=p[1];
            for(int i=2;i<=p[0];i++) ans=min(ans,p[i]);  
            printf("%lld\n",ans);
        }
    }
    return 0;
}
View Code

 

posted @ 2018-01-09 22:54  啊宸  阅读(208)  评论(0编辑  收藏  举报