Prime Test
题目大意:给出一个正整数n,判断其是否为素数,如果是则输出Prime,否则输出n的最小素因子
解题思路:因为 2<=n<2^54 ,n的取值太大了,所以判素数要用Miller-Rabin素数判定,如果不是素数则用Pollard-rho算法对n素因子分解找出最小素因子。
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<time.h>
using namespace std;
#define maxn 111
typedef long long ll;
int Times=20;
ll mod_mul(ll a,ll b,ll p)
{
ll ans=0ll;
a%=p,b%=p;
if(a>b) swap(a,b);
while(b)
{
if(b&1) ans=(ans+a)%p;
a=(a+a)%p;
b>>=1;
}
return ans;
}
ll mod_pow(ll a,ll b,ll p)
{
ll ans=1ll;
a%=p;
while(b)
{
if(b&1) ans=mod_mul(ans,a,p);
a=mod_mul(a,a,p);
b>>=1;
}
return ans;
}
bool witness(ll a,ll n)
{
ll m=n-1;
int j=0;
while((m&1)==0)
{
j++;
m>>=1;
}
ll x=mod_pow(a,m,n);
if(x==1||x==n-1) return 0;
while(j--)
{
x=(x*x)%n;
if(x==n-1) return 0;
}
return 1;
}
bool Miller_Rabin(ll n)//判断n是不是素数
{
srand(time(0));
if(n<2) return 0;
if(n==2) return 1;
if((n&1)==0) return 0;
for(int i=0;i<Times;i++)
{
ll a=rand()%(n-1)+1;
if(witness(a,n)) return 0;
}
return 1;
}
ll factor[maxn];//质因数分解结果(刚返回时是无序的)
int res;//质因数的个数
ll gcd(ll a,ll b)
{
if(a==0)return 1;
if(a<0)return gcd(-a,b);
while(b)
{
ll t=b;b=a%b;a=t;
}
return a;
}
ll Pollard_Rho(ll x,ll c)
{
ll i=1,k=2;
ll x0=rand()%x;
ll y=x0;
while(1)
{
i++;
x0=(mod_mul(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 Find_Factor(ll n)//对n进行素因子分解
{
if(Miller_Rabin(n))//n是素数
{
factor[res++]=n;
return ;
}
ll p=n;
while(p>=n)p=Pollard_Rho(p,rand()%(n-1)+1);
Find_Factor(p);
Find_Factor(n/p);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll n,ans;
scanf("%lld",&n);
if(Miller_Rabin(n)) //判定是否为素数
{
printf("Prime\n");
continue;
}
res=0;
Find_Factor(n); //分解素数
ans=factor[0];
for(int i=1;i<res;i++)
ans=min(ans,factor[i]);
printf("%lld\n",ans);
}
return 0;
}