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; }