题目较难,Miller_Rabin判断素数+Pollard_rho求整数素因子
上面两种算法就不再介绍了,直接给出代码,详见注释。
下面是代码:156K+907MS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#define Test 20
#define Max 110
#define Inf 1000001000
using namespace std;
//__int64 factor[Max];
//__int64 num,m;
__int64 m,min_value;
int Case;
__int64 mult_mod(__int64 a,__int64 b,__int64 mod){ //(a*b)%mod
a%=mod;
b%=mod;
__int64 result=0;
while(b){
if(b&1){
result+=a;
result%=mod;
}
a<<=1;
if(a>=mod) a%=mod;
b>>=1;
}
return result;
}
__int64 pow_mod(__int64 x,__int64 n,__int64 mod){ //(x^n)%mode
if(n==0)
return 1%mod;
__int64 result=1;
while(n){
if(n&1)
result=mult_mod(result,x,mod);
x=mult_mod(x,x,mod);
n>>=1;
}
return result;
}
bool check(__int64 a,__int64 x,__int64 n,int t){
//以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数
//一定是合数返回true,不一定返回false
__int64 ret=pow_mod(a,x,n);
__int64 last=ret;
for(int i=1;i<=t;i++){
ret=mult_mod(ret,ret,n);
if(ret==1 && last!=1 && last!=n-1)
return true; //合数
last=ret;
}
if(ret!=1)
return true;
return false;
}
// Miller_Rabin()算法素数判定,是素数返回true.(可能是伪素数,但概率极小合数返回false;
bool Miller_Rabin(__int64 n){
if(n<2) return false;
if(n==2) return true;
if((n&1)==0) return false;
__int64 x=n-1;
int t=0;
while(!(x&1)){
x>>=1;
t++;
}
for(int i=0;i<Test;i++){
__int64 a=rand()%(n-1)+1;
if(check(a,x,n,t))
return false;
}
return true;
}
//====Pollard_rho
__int64 gcd(__int64 a,__int64 b){
if(a==0) return b;
else if(a<0) return gcd(-a,b);
while(b){
__int64 t=b;
b=a%b;
a=t;
}
return a;
}
__int64 Pollard_rho(__int64 x,__int64 c){ //Pollard_rho算法进行质因子分解
__int64 i=1,k=2;
__int64 x0=rand()%x;
__int64 y=x0;
while(true){
i++;
x0=(mult_mod(x0,x0,x)+c)%x;
__int64 d=gcd(y-x0,x);
if(d!=1 && d!=x) return d;
if(y==x0) return x;
if(i==k){
y=x0,k+=k;
}
}
}
void findfac(__int64 n){ //寻找质因子
if(Miller_Rabin(n)){
//factor[num++]=n;
if(n<min_value)
min_value=n;
return ;
}
__int64 p=n;
while(p>=n) p=Pollard_rho(p,rand()%(n-1)+1);
findfac(p);
findfac(n/p);
}
int main(){
scanf("%d",&Case);
srand(time(NULL));
while(Case--){
scanf("%I64d",&m);
if(Miller_Rabin(m))
printf("Prime\n");
else{
min_value=Inf;
findfac(m);
printf("%I64d\n",min_value);
}
}
return 0;
}