虽然很久以前就听说过PR算法,但前几天第一次打。
首先miller rabin判断素数,不在复杂度瓶颈。
pollard rho倍增环长,复杂度是\(O(n^{\frac{1}{4}} log n)\)的。
然而这样复杂度较高,比较难过加强后的数据。
可以考虑每次倍增时把乘积存下来,然后在增加环长时一次gcd,这样应该是\(O(n^{\frac{1}{4}})\)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")#include <bits/stdc++.h>
using namespace std;
typedef long long i64;
typedef unsigned long long u64;
typedef vector<i64> vi64;
i64 fast_pow(i64 x,i64 y,i64 z){//cerr<<"fp"<<x<<" "<<y<<" "<<z<<endl;i64 ret=1;for (; y; y>>=1,x=(__int128)x*x%z)if (y&1) ret=(__int128)ret*x%z;return ret;
}
u64 RAND(){return ((u64)rand()*rand()+rand());
}
const int sp[]={2,3,5,7,11,13,17,19,23,29,31,37,43,47};
bool is_prime(i64 n){//cerr<<"is_prime"<<n<<endl;if (n==2) return 1;if (~n&1) return 0;i64 u=n-1;int b=0;while (~u&1){u>>=1;++b;}for (int i=0; i<12&&sp[i]<n; ++i){i64 now=fast_pow(sp[i],u,n),la=now;//cerr<<a<<" "<<u<<" "<<now<<" "<<i<<endl;if (now!=1)for (int i=1; i<=b; ++i){now=(__int128)now*now%n;if (now==1){if (la!=n-1) return 0;break;}la=now;}//cerr<<"now"<<now<<endl;if (now!=1) return 0;}return 1;
}
i64 fix(i64 a,i64 n){return a<0?a+n:a;
}
i64 gcd(i64 a,i64 b){int shift=__builtin_ctzll(a|b);b>>=__builtin_ctzll(b);while (a){a>>=__builtin_ctzll(a);if (a<b) swap(a,b);a-=b;}return b<<shift;
}
i64 pollard_rho(i64 n,i64 c){//cerr<<"pollard_rho"<<n<<" "<<c<<endl;i64 i=1,k=2,x=RAND()%(n-1)+1,y=x,g=1;while (1){++i;x=((__int128)x*x+c)%n;//i64 tmp=gcd(fix(x-y,n),n);//cerr<<x<<" "<<y<<endl;//if (tmp>1) return tmp;g=(__int128)fix(x-y,n)*g%n;if (i==k){g=gcd(g,n);if (g>1){if (g==n){x=y;while (g==1){x=((__int128)x*x+c)%n;g=gcd(fix(x-y,n),n);}}return g;}y=x;k<<=1;}}
}
vi64 v;
void fj(i64 n){if (n==1) return;if (is_prime(n)){//cerr<<"N"<<n<<endl;v.push_back(n);return;}i64 p=n;while (p>=n){p=pollard_rho(n,RAND()%n);}fj(p);fj(n/p);
}
typedef vector<pair<i64,int> > vpi64i;
vpi64i vv;
int k,p;
int fp(int x,int y){int ret=1;for (; y; y>>=1,x=(i64)x*x%p) if (y&1) ret=(i64)ret*x%p;return ret;
}
int C(int x){return ((u64)x*(x+1)>>1)%p;
}
int mul(int x,int y){return (i64)x*y%p;
}
int add(int x,int y){return (x+=y)>=p?x-p:x;
}
int main(){int t;cin>>t;while (t--){i64 n;cin>>n;//FastDiv fd(p);if (n==1){cout<<1<<'\n';continue;}v.clear();fj(n);sort(v.begin(),v.end());(v.back()==n?cout<<"Prime":cout<<v.back())<<'\n';}
}