说实在的,这题当初完全不懂。上网查了别人的AC代码,感觉也没看懂。后来,一怒之下,把算法导论买了。。。看完相关知识后,才发觉,没有想象中的复杂。。
但话又说回来,其实因式分解这一块还是比较难的。但在这题,只要求最小素因子,所以比较简单。其思想是一种二分。
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>
#define s 30//随机测试数
typedef long long ll;
ll min;
ll multi(ll a,ll b,ll m){
ll ans=0;
while(a){
if(a&1){
ans=(ans+b)%m;
a>>=1;
b=b*2%m;
}
else{
a>>=1;
b=b*2%m;
}
}
return ans;
}
ll pow(ll a,ll b,ll m){
ll ans=1;
ll x=a;
while(b){
if(b&1){
ans=multi(ans,x,m);
x=multi(x,x,m);
b>>=1;
}
else{
x=multi(x,x,m);
b>>=1;
}
}
return ans;
}
bool check(ll n){
ll a=rand()%(n-1)+1;
int t=0;
ll r=n-1;
while(!(r%2)){
r>>=1;
t++;
}
ll x=pow(a,r,n);
for(int i=1;i<=t;i++){
ll y=multi(x,x,n);
if(y==1&&x!=1&&x!=n-1)
return 0;
x=y;
}
if(x!=1)
return 0;
return 1;
}
bool prime(ll n){
if(n==2)return 1;
if(n%2==0)return 0;
for(int i=1;i<=s;i++)
if(!check(n))
return 0;
return 1;
}
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
ll rho(ll n,int c){
ll x=rand()%(n-1);
ll y=x,d;
int k=2,i=1;
while(1){
i++;
x=(multi(x,x,n)+c)%n;
d=gcd(y-x,n);
if(d>1&&d<n)
return d;
if(x==y)
return n;
if(i==k){
y=x;
k<<=1;
}
}
}
void find(ll n,int c){
if(n==1)return;
ll p=n;
if(prime(n)){
if(min>n)min=n;
}
else{
while(p>=n)
p=rho(n,c--);
find(n/p,c);
find(p,c);
}
}
int main(){
freopen("t.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
ll n;
scanf("%lld",&n);
if(prime(n))
printf("Prime\n");
else {
min=n;
int c=10452;//随机测试数
find(n,c);
printf("%lld\n",min);
}
}
return 0;
}