1. 程式人生 > >BZOJ.3667.Rabin-Miller算法(MillerRabin PollardRho)

BZOJ.3667.Rabin-Miller算法(MillerRabin PollardRho)

.net lin del line detail double 題目 隨機 ++

題目鏈接
Pollard_Rho:http://blog.csdn.net/thy_asdf/article/details/51347390

#include<cstdio>
#include<cctype>
#include<algorithm>
#define gc() getchar()
const int p[]={2,3,5,7,11,13,17,19};
typedef long long LL;
LL Ans;

inline LL read()
{
    LL now=0,f=1;register char c=gc();
    for(;!isdigit(c);c=gc()) if
(c=='-') f=-1; for(;isdigit(c);now=now*10+c-'0',c=gc()); return now*f; } inline LL Mult(LL a,LL b,LL p)//O(1)快速乘 { LL tmp=a*b-(LL)((long double)a/p*b+1e-8)*p; return tmp<0?tmp+p:tmp; } LL Fast_Pow(LL n,LL k,LL p) { LL t=1; for(;k;k>>=1,n=n*n%p) if(k&1
) t=t*n%p; return t; } bool Miller_Rabin(LL n) { if(n==2) return 1; if(!(n&1)||n==1) return 0; for(int i=0;i<8;++i) if(n==p[i]) return 1; else if(!(n%p[i])) return 0; LL u=n-1,now,las; int t=0; while(!(u&1)) u>>=1,++t; for(int i=0;i<8;++i) { now=Fast_Pow(p[i],u,n); for
(int j=1;j<=t;++j) { las=now, now=Mult(now,now,n); if(now==1&&las!=1&&las!=n-1) return 0; } if(now!=1) return 0; } return 1; } LL gcd(LL x,LL y) { return y?gcd(y,x%y):x; } LL Rho(LL n,LL delta) {//現要分解n,有兩個隨機數x,y,若p=gcd(x-y,n)!=1&&p!=n,那麽p為n的一個約數...省略 LL x=rand()%n,y=x,p=1; int k=2;//設定k為此次路徑長 for(int i=1;p==1;++i) { x=(Mult(x,x,n)+delta)%n;//隨機函數f(x)=x*x+d p=gcd(std::abs(x-y),n);//多次生成隨機數,直至找到p是n的一個因子 if(i==k) y=x,k<<=1;//達到k次後把y賦值為x。路徑每次倍長 } return p; } void Find(LL n) { if(n==1) return; if(Miller_Rabin(n)) {Ans=std::max(Ans,n);/*fac[++cnt]=n;*/ return;} LL t=n; while(t==n) t=Rho(n,rand()%(n-1)+1); //t=n說明這個隨機函數會導致走到n的環上,再換一個重試即可 Find(t), Find(n/t); } int main() { #ifndef ONLINE_JUDGE freopen("3667.in","r",stdin); #endif int t=read();LL n; while(t--) n=read(),Ans=0,Find(n),Ans==n?puts("Prime"):printf("%lld\n",Ans); return 0; }

BZOJ.3667.Rabin-Miller算法(MillerRabin PollardRho)