【刷題】BZOJ 3667 Rabin-Miller算法
阿新 • • 發佈:2018-03-04
click solution long 輸出 算法 概率 lap srand template
2
13
134
8897
1234567654321
1000000000000
Prime
67
41
4649
5
Input
第一行:CAS,代表數據組數(不大於350),以下CAS行,每行一個數字,保證在64位長整形範圍內,並且沒有負數。你需要對於每個數字:第一,檢驗是否是質數,是質數就輸出Prime
第二,如果不是質數,輸出它最大的質因子是哪個。
Output
第一行CAS(CAS<=350,代表測試數據的組數)
以下CAS行:每行一個數字,保證是在64位長整形範圍內的正數。
對於每組測試數據:輸出Prime,代表它是質數,或者輸出它最大的質因子,代表它是和數
Sample Input
62
13
134
8897
1234567654321
Sample Output
PrimePrime
67
41
4649
5
HINT
數據範圍:
保證cas<=350,保證所有數字均在64位長整形範圍內。
Solution
裸Pollard Rho題
但它不簡單,反而很惡心
不知道為什麽數據那麽強
幾個註意的:
1)乘法要寫快速乘,原理是a%b=a-a/b*b
2)Miller Rabin最好優化
3)有些版本的Pollard Rho是錯的。。。被坑了好久(數學一本通)
這東西本身有概率錯誤,導致調都不知道調哪裏,最後是照著zhou888的代碼一點一點邊改邊交邊調的
#include<bits/stdc++.h> #define ll unsigned long long const int Count=5; int base[6]={0,2,3,5,7,61}; ll ans; template<typename T> inline void read(T &x) { T data=0,w=1; char ch=0; while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar(); if(ch==‘-‘)w=-13667 Rabin-Miller算法,ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘)data=((T)data<<3)+((T)data<<1)+(ch^‘0‘),ch=getchar(); x=data*w; } template<typename T> inline void write(T x,char c=‘\0‘) { if(x<0)putchar(‘-‘),x=-x; if(x>9)write(x/10); putchar(x%10+‘0‘); if(c!=‘\0‘)putchar(c); } template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);} template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);} inline ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } inline ll qmul(ll a,ll b,ll n) { return (a*b-(ll)(((long double)a*b+0.5)/n)*n+n)%n; } inline ll qexp(ll a,ll b,ll n) { ll res=1; while(b) { if(b&1)res=qmul(res,a,n); a=qmul(a,a,n); b>>=1; } return res; } inline bool Miller_Rabin(ll N) { if(N==1||(N>3&&N%6!=1&&N%6!=5))return false; for(register int i=1;i<=4;++i) if(N==base[i])return true; else if(N%base[i]==0)return false; ll p=N-1,A,pre,k=0; while(!(p&1))p>>=1,++k; for(register int i=1;i<=Count;++i) { A=rand()%(N-1)+1; A=qexp(A,p,N); pre=A; for(register int j=1;j<=k;++j) { A=qmul(A,A,N); if(A==1&&pre!=1&&pre!=N-1)return false; pre=A; } if(A!=1)return false; } return true; } inline ll abs(ll x,ll y) { return y>x?y-x:x-y; } inline int Pollard_Rho(ll N,ll C) { ll k=2,x=rand()%N,y=x,d=1; for(register ll i=1;d==1;++i) { x=(qmul(x,x,N)+C)%N; d=gcd(abs(x,y),N); if(i==k)k<<=1ll,y=x; } return d; } inline void solve(ll N) { if(N==1)return ; if(Miller_Rabin(N)) { chkmax(ans,N); return ; } ll p,c=1; while((p=Pollard_Rho(N,c))==N&&c<=N)c++; solve(p);solve(N/p); } int main() { srand(2523452); int T; read(T); while(T--) { ll N; read(N); ans=0; solve(N); if(ans==N)puts("Prime"); else write(ans,‘\n‘); } return 0; }
【刷題】BZOJ 3667 Rabin-Miller算法