题意:
给你一个数,判断是否是素数,是的话输出prime 不是素数输出最小因子。
题解:
快速判质Miller_Rabin 算法, 根据费马小定理 a^(p-1)%p==1 检测是否符合素数性质,当然有伪素数,不过概率很小,多测几次就行了。
然后Pollard 分解因子,顺序是无序的,然后找到最小的那个。
poj g++ 无法使用 srand()函数,
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define ll __int64
using namespace std;
const int S=8;
ll ans;
ll gcd(ll a,ll b){
ll t;
while(b){
t=a;a=b;
b=t%b;
}
if(a>=0) return a;
else return -a;
}
ll mul_mod(ll a,ll b,ll c){
a%=c;
b%=c;
ll ret=0;
ll tem=a;
while(b){
if(b&1){
ret+=tem;
if(ret>c) ret-=c;
}
tem<<=1;
if(tem>c) tem-=c;
b>>=1;
}
return ret;
}
ll pow_mod(ll a,ll n,ll mod){
ll ret=1;
ll temp=a%mod;
while(n){
if(n&1)ret=mul_mod(ret,temp,mod);
temp=mul_mod(temp,temp,mod);
n>>=1;
}
return ret;
}
bool check(ll a,ll n,ll x,ll t){
ll ret=pow_mod(a,x,n);
ll last=ret;
for(int i=1;i<=t;++i){
ret=mul_mod(ret,ret,n);
if(ret==1&&last!=1&&last!=n-1) return true;
last=ret;
}
if(ret!=1) return true;
else return false;
}
bool Miller_Rabin(ll n){
if(n<2) return false;
if(n==2) return true;
if((n&1)==0) return false;
ll x=n-1;
ll t=0;
while((x&1)==0) {x>>=1;t++;}
//srand(time(NULL));
for(int i=0;i<S;++i){
ll a=rand()%(n-1)+1;
if(check(a,n,x,t))
return false;
}
return true;
}
ll Pollard(ll x, ll c) //对n进行因字分解,找出n的一个因子,注意该因子不一定是最小的
{
ll i=1,k=2;
//srand(time(NULL));
ll x0=rand()%(x-1)+1;
ll y=x0;
while (true) {
i++;
x0 = (mul_mod(x0, x0, x) + c) % x;
ll 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 solve(ll x,ll c){
ll ret,m;
if(x==1) return ;
if(Miller_Rabin(x)){
if(x<ans)
ans=x;
return ;
}
m=x;
ll k=c;
while(m>=x)
m=Pollard(x,k--);
solve(m,c);
solve(x/m,c);
}
int main(){
int T;
ll p;
scanf("%d",&T);
while(T--){
scanf("%lld",&p);
ans=p;
if(Miller_Rabin(p)) puts("Prime");
else {
solve(p,107);
printf("%I64d\n",ans);
}
}
return 0;
}