本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:POJ1811
正解:$Pollard-rho$
解题报告:
$Pollard-rho$算法模板题。
学习$Pollard-rho$,左转上一篇题解.
//It is made by ljh2000
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <ctime>
using namespace std;
typedef long long LL;
vector<LL>w;
inline LL mul(LL x,LL y,LL mod){ LL r=0; while(y>0) { if(y&1) r+=x,r%=mod; x+=x; x%=mod; y>>=1; } return r; }
inline LL fast_pow(LL x,LL y,LL mod){ LL r=1; while(y>0) { if(y&1) r=mul(r,x,mod); x=mul(x,x,mod); y>>=1; } return r; }
inline LL nex(LL x,LL c,LL mod){ return (mul(x,x,mod)+c)%mod; }
inline LL gcd(LL x,LL y){ if(y==0) return x; return gcd(y,x%y); }
inline LL ABS(LL x){ if(x<=0) return -x; return x; }
inline LL Miller_Rabin(LL n){
if(n==1) return 0; if(n==2) return 1; if(!(n&1)) return 0;
int T=5; LL aa,nn=n-1,k=0,bb,cc;
while(!(nn&1)) nn>>=1,k++;
while(T--) {
aa=rand()%(n-1)+1;
bb=fast_pow(aa,nn,n);
for(int i=1;i<=k;i++) {
cc=mul(bb,bb,n);
if(cc==1 && bb!=1 && bb!=n-1) return 0;
bb=cc;
}
if(bb!=1) return 0;
}
return 1;
}
inline void Pollard_rho(LL n){
while(!(n&1)) n>>=1,w.push_back(2);
if(n==1) return ;
if(Miller_Rabin(n)) { w.push_back(n); return ; }
LL x=rand()%(n-1)+1,y=x,c=rand()%(n-1)+1,g;
while(1) {
bool flag=true;
for(int i=1,j=2;;i++) {
x=nex(x,c,n);
if(x==y) { flag=false; break; }
g=gcd(ABS(x-y),n);
if(g>1 && g<n) break;
if(i==j) y=x,j<<=1;
}
if(flag) break;
}
Pollard_rho(n/g); Pollard_rho(g);
}
inline void work(){
//srand(time(NULL));
srand(1197993966);
int T; scanf("%d",&T);
LL n;
while(T--) {
scanf("%lld",&n); if(Miller_Rabin(n)) { puts("Prime"); continue; }
w.clear(); Pollard_rho(n);
sort(w.begin(),w.end());
printf("%lld\n",w[0]);
}
}
int main()
{
work();
return 0;
}
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。