传送门
题意:判断一个long long范围内的大数,是否为质数,如果是输出Prime,否则输出最大的因子。
分析:随机测试和大数分解模板题。
//#include<bits/stdc++.h>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
//****************************************************************
// Miller_Rabin 算法进行素数测试
//速度快,而且可以判断 <2^63的数
//****************************************************************
typedef long long LL;
const int S=10;
LL mult_mod(LL a,LL b,LL mod) //计算(a+b)%mod 防止爆 long long
{
a%=mod;
b%=mod;
LL ret=0,tem=a;
while(b)
{
if(b&1)
{
ret+=tem;
if(ret>mod)ret-=mod;
}
tem<<=1;
if(tem>mod)tem-=mod;
b>>=1;
}
return ret;
}
LL pow_mod(LL a,LL n,LL mod) //快速幂计算a^b%mod
{
LL ret=1,temp=a%mod;
while(n)
{
if(n&1)ret=mult_mod(ret,temp,mod);
temp=mult_mod(temp,temp,mod);
n>>=1;
}
return ret;
}
//通过a^(n-1)=1(mod n)判断n是否为质数
//n-1=x*2^t中间使用二次判断
//是合数返回true,不是不一定返回false
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=mult_mod(ret,ret,n);
if(ret==1&&last!=1&&last!=n-1)return true;
last=ret;
}
if(ret!=1)return true;
return false;
}
//是素数返回true
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,t=0;
while((x&1)==0)x>>=1,t++;
for(int i=0;i<S;i++)
{
LL a=rand()%(n-1)+1;
if(check(a,n,x,t))
return false;
}
return true;
}
LL fac[100];
int tot=0;
LL gcd(LL a,LL b)
{
LL t;
if(a<0)a=-a;
while(b)
{
t=a;
a=b;
b=t%b;
}
return a;
}
LL pollard_rho(LL x,LL c)
{
LL i=1,k=2;
LL x0=rand()%(x-1)+1;
LL y=x0;
while(1)
{
i++;
x0=(mult_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 findfac(LL n,int k)
{
if(n==1)return ;
if(Miller_Rabin(n))
{
fac[++tot]=n;
return;
}
LL p=n;
int c=k;
while(p>=n)
p=pollard_rho(p,c--);
findfac(p,k);
findfac(n/p,k);
}
int main()
{
int TA;
LL n;
scanf("%d",&TA);
while(TA--)
{
scanf("%I64d",&n);
if(Miller_Rabin(n))printf("Prime\n");
else
{
tot=0;
findfac(n,107);
long long ans=fac[1];
for(int i=2;i<=tot;i++)
if(fac[i]<ans)
ans=fac[i];
printf("%I64d\n",ans);
}
}
}