题意:大整数判断素数,非素则求最小质因子。
Pollard-Rho和Miller-Rabin各种纠结,自己的模版各种TLE,只好去copy别人的。Orz
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#define time 12
using namespace std;
const long long max1 = (long long)pow((double)2,(double)60) ;
long long min1;
long long gcd(long long x,long long y){
return y==0?x:gcd(y, x%y);
}
long long Mulmode(long long a,long long b,long long c){ //计算(a*b) mod n
long long ret = 0;
while(b){
if(b & 1)
ret = (ret + a) % c;
a = (a << 1) % c;
b = b >> 1;
}
return ret ;
}
long long powmode(long long a,long long b,long long c){ //计算(a^b) mod n
long long ret = 1;
while(b ){
if(b & 1)
ret = Mulmode(ret,a,c);
a = Mulmode(a,a,c);
b = b >> 1;
}
return ret ;
}
bool witness(long long a,long long n){ //以a为基对n进行Miller测试并实现二次探测
long long m,x,y;
int i,j = 0;
m = n - 1;
while(m % 2 == 0){
m = m >> 1;
j ++;
}
x = powmode(a ,m ,n );
for(i = 1;i <= j ;i ++){
y = powmode(x,2,n);
if((y == 1) && (x != 1) && (x != n - 1))
return true;
x = y;
}
if(y != 1)
return true;
return false;
}
bool miller_rabin(long long n ,long long s){
long long a;
int i ;
if(n == 1)
return false ;
if(n == 2)
return true;
if(n % 2 == 0)
return false;
for(i = 1;i <= s; i ++){
a = rand() % (n - 1) + 1;
if(witness(a,n))
return false;
}
return true;
}
long long pollard_rho(long long n ,long long c ){
long long i,k,x,y,d;
i = 1;
k = 2;
x = rand() % n;
y = x;
while(true){
i ++ ;
x = (Mulmode(x, x, n) + c) % n;
d = gcd( y - x , n );
if( d > 1 && d < n ) return d;
if(y == x ) return n;
if(i == k ){
y = x;
k = k << 1;
}
}
}
void get_small(long long n,long long c){
long long m;
if(n == 1)
return;
if(miller_rabin(n,time)){
if(n < min1 )
min1 = n;
return;
}
m = n;
while(m == n )
m = pollard_rho(n, c--);
get_small(m , c);
get_small(n/m, c);
}
int main(){
long long n;
int T;
cin>>T;
while(T--){
scanf("%I64d",&n);
min1 = max1;
if(miller_rabin(n,time))
printf("Prime\n");
else {
get_small(n,200);
printf("%I64d\n", min1);
}
}
return 0;
}