HDU3988 大整數質因數分解【Miller_Rabin 進行素數判定+Pollard_rho對整數進行因數分解】
阿新 • • 發佈:2018-12-02
iSea is tired of writing the story of Harry Potter, so, lucky you, solving the following problem is enough.
Input
The first line contains a single integer T, indicating the number of test cases.
Each test case contains two integers, N and K.
Technical Specification
1. 1 <= T <= 500
2. 1 <= K <= 1 000 000 000 000 00
3. 1 <= N <= 1 000 000 000 000 000 000
Output
For each test case, output the case number first, then the answer, if the answer is bigger than 9 223 372 036 854 775 807, output “inf” (without quote).
Sample Input
2
2 2
10 10
Sample Output
Case 1: 1
Case 2: 2
#include <bits/stdc++.h> #define X 10005 #define inF 0x3f3f3f3f #define PI 3.141592653589793238462643383 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; const int N = 1e4; const int Times=10; const ll inf= 9223372036854775807; ll ct,cnt; ll fac[N],num[N]; ll gcd(ll a,ll b) { if(!b) return a; else gcd(b,a%b); } ll mul_mod(ll a,ll b,ll m) { ll ans=0; while(b) { if(b&1) { ans=(ans+a)%m; } a=(a+a)%m; b>>=1; } return ans; } ll Pow_mod(ll a, ll b,ll m) { ll ans=1; a%=m; while(b) { if(b&1) { ans=mul_mod(ans,a,m);//ans=ans*a%m; } a=mul_mod(a,a,m);//a=a*a%m; b>>=1; } return ans; } bool Miller_Rabin(ll n) { if(n==2) return true; if(n<2||!(n&1)) return false; ll a,m=n-1,x,y; int k=0; // while((m&1)==0)//判奇數 // { // k++; // m>>=1; // } while (~m & 1) //找到奇數 { m >>= 1; k++; } for(int i=0;i<Times;++i) { a=rand()%(n-1)+1; x=Pow_mod(a,m,n); for(int j=0;j<k;++j) { y=mul_mod(x,x,n); if(y==1&&x!=1&&x!=n-1) return false; x=y; } if(y!=1) //a^(2*k*r)%m=1 return false; } return true; } ll f(ll x,ll n) { return (mul_mod(x,x,n)+2)%n; } ll Pollard_rho(ll n,ll c) { ll x,y,d,i=1,k=2; y=x=rand()%(n-1)+1; while(true) { i++; x=f(x,n);//x=(mul_mod(x,x,n)+c)%n; d=gcd((y-x+n)%n,n); if(1<d&&d<n) return d; if(y==x) return n;//沒有隨機查詢素因子失敗,返回 if(i==k) { y=x; k<<=1; } } // do // { // i++; // x=f(x,n);//(mul_mod(x,x,n)+c)%n; // d=gcd((y-x+n)%n,n); // if(1<d&&d<n) // return d; //// if(y==x) //// return n;//沒有隨機查詢素因子失敗,返回 // if(i==k) // { // y=x; // k<<=1; // } // }while(y!=x); return n; } ll get(ll p,ll n) { ll ans=0; while(n) { ans+=n/p;/// no n/=p; } return ans; } void Find(ll n,int c) { if(n==1) return ; if(Miller_Rabin(n)) { fac[ct++]=n; return ; } ///不是素數: ll p = n, k = c; while(p>=n) p = Pollard_rho(p,c);///找到n的一個因子,但是現在還不能保證是一個素因子,要進行Miller_rabin素數檢測 Find(p,k); Find(n/p,k);//因為n是偶數 } int main() { ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); int t=1,tt=1; ll n,k,minx; cin>>t; for(int Case=1;Case<=t;++Case) { cin>>n>>k; cout<<"Case "<<Case<<": "; if(k==1) { cout<<"inf"<<endl; continue; } ct=0; Find(k,2); sort(fac,fac+ct); num[0]=1; int k=1; for(int i=1;i<ct;++i) { if(fac[i]==fac[i-1]) { num[k-1]++; } else { num[k]=1; fac[k++]=fac[i]; } } cnt=k; minx=inf; for(int i=0;i<cnt;++i) { ll tmp=get(fac[i],n)/num[i]; minx=min(minx,tmp); } if(minx==inf) cout<<"inf"<<endl; else cout<<minx<<endl; } return 0; } /* 對大整數進行質因數分解 採用 Miller_Rabin 進行素數判定 + Pollard_rho 對整數進行因數分解(Mill_Rabin 判定是否是素數因子) */