1. 程式人生 > >【BZOJ3667】Rabin-Miller演算法(Pollard_pho演算法)

【BZOJ3667】Rabin-Miller演算法(Pollard_pho演算法)

Input

第一行:CAS,代表資料組數(不大於350),以下CAS行,每行一個數字,保證在64位長整形範圍內,並且沒有負數。你需要對於每個數字:第一,檢驗是否是質數,是質數就輸出Prime
第二,如果不是質數,輸出它最大的質因子是哪個。

Output

第一行CAS(CAS<=350,代表測試資料的組數)
以下CAS行:每行一個數字,保證是在64位長整形範圍內的正數。
對於每組測試資料:輸出Prime,代表它是質數,或者輸出它最大的質因子,代表它是和數

Sample Input

6

2

13

134

8897

1234567654321

1000000000000

Sample Output

Prime

Prime

67

41

4649

5

HINT

資料範圍:

保證cas<=350,保證所有數字均在64位長整形範圍內。

題解:
模板題。這是一個比較冷門的但還比較有用的數論知識,不會的可以看:
Miller-Rabin演算法&Pollard_pho演算法
是裸的模板,但是出題人硬要卡常非常有趣,但是要優化常數,乘法要自己用long double轉一下,不然會TLE。

模板:(BZOJ3667)

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h> #include<math.h> #define ll long long #define inf 0x7f7f7f7f #define il inline using namespace std; const ll a[]={2,3,5,7,11,13,17,19,23,29}; il ll read() { ll x=0,f=1; char c=getchar(); while(c<'0' || c>'9') {if(c=='-') f=-1;c=getchar();} while(c<='9'
&& c>='0') {x=x*10+c-'0';c=getchar();} return x*f; } int n; ll mx,x; ll gcd(ll a,ll b) { if(!b) return a; return gcd(b,a%b); } il ll mul(ll a,ll b,ll p) { ll tmp=(a*b-(ll)((long double)a/p*b+1e-8)*p); return tmp<0?tmp+p:tmp; } il ll pow(ll a,ll b,ll p) { ll ans=1;a%=p; while(b) { if(b&1) ans=mul(ans,a,p); a=mul(a,a,p); b>>=1; } return ans; } il bool check(ll a,ll n,ll r,ll s) { ll ans=pow(a,r,n),p=ans; for(int i=1;i<=s;i++) { ans=mul(ans,ans,n); if(ans==1 && p!=1 && p!=n-1) return 1; p=ans; } if(ans!=1) return 1; return 0; } il bool MR(ll n) { if(n<=1) return 0; ll r=n-1,s=0; while(r%2==0) r>>=1,s++; for(int i=0;i<10;i++) { if(a[i]==n) return 1; if(check(a[i],n,r,s)) return 0; } return 1; } il ll rho(ll n,ll c) { ll k=2,x=rand()%n,y=x,p=1; for(ll i=1;p==1;i++) { x=(mul(x,x,n)+c)%n; p=x>y ? x-y : y-x; p=gcd(n,p); if(i==k) y=x,k+=k; } return p; } void solve(ll n) { if(n==1) return; if(MR(n)) {mx=max(mx,n);return;} ll t=n; while(t==n) t=rho(n,rand()%(n-1)); solve(t);solve(n/t); } int main() { n=read(); while(n--) { x=read(); mx=0; solve(x); if(mx==x) puts("Prime"); else printf("%lld\n",mx); } return 0; }