1. 程式人生 > >Pollard's Rho演算法總結

Pollard's Rho演算法總結

先貼一份程式碼在這。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <ctime>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;

inline LL read(){
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}

LL n,ans,mi[6]={2,3,5,7,11,13};

inline LL gcd(LL x,LL y){
    if(!x||!y) return x+y;
    while(y){
        std::swap(x,y);
        y%=x;
    }
    return x;
}

inline LL qpow(LL x,LL y,LL mod){
    LL ret=1,tt=x%mod;
    while(y){
        if(y&1) ret=(__int128)ret*tt%mod;
        tt=(__int128)tt*tt%mod;
        y>>=1;
    }
    return ret;
}

bool miller_rabin(LL num){
    if(num<2) return 0;
    if(num==2||num==3||num==5||num==7||num==11||num==13) return 1;
    if(num%2==0||num%3==0||num%5==0||num%7==0||num%11==0||num%13==0) return 0;
    LL temp=num-1;int cnt2=0;
    while(!(temp&1)) temp>>=1,cnt2++;
    rin(i,0,5){
        LL now=qpow(mi[i],temp,num);
        if(now==1||now==num-1) continue;
        rin(j,1,cnt2){
            now=(__int128)now*now%num;
            if(now==num-1) break;
            if(j==cnt2) return 0;
        }
    }
    return 1;
}

LL pollard_rho(LL num){
    LL fixx=rand()%(num-1)+1,siz=2,x=fixx,fac=1;
    LL b=rand()%(num-1)+1;
    while(fac==1){
        rin(i,1,siz){
            x=((__int128)x*x+b)%num;
            fac=gcd(std::abs(x-fixx),num);
            if(fac>1) return fac;
        }
        siz<<=1;
        fixx=x;
    }
}

void getdivisor(LL num){
    if(num==1||num<=ans) return; 
    if(miller_rabin(num)){
        ans=std::max(ans,num);
        return;
    }
    LL x=num;
    while(x==num) x=pollard_rho(x);
    while(num%x==0) num/=x;
    if(num<x) std::swap(num,x);
    getdivisor(num);
    getdivisor(x);
}

int main(){
    int T=read();
    while(T--){
        n=read();
        ans=1;
        getdivisor(n);
        if(ans==n) printf("Prime\n");
        else printf("%lld\n",ans);
    }
    return 0;
}