应用:Miller_Rabin算法 和Pollard_rho 算法
Given a big integer number, you are required to find out whether it's a prime number.
Input
The first line contains the number of test cases T (1 <= T <= 20 ), then the following T lines each contains an integer number N (2 <= N < 2 54).
Output
For each test case, if N is a prime number, output a line containing the word “Prime”, otherwise, output a line containing the smallest prime factor of N.
Sample Input
2
5
10
Sample Output
Prime
2
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cstdlib>
#define C 240
#define TIME 10
#define LL long long
using namespace std;
LL ans;
LL gcd(LL a, LL b)
{
if(a==0) return 1;
if(a<0) return gcd(-a,b);
return b==0?a:gcd(b,a%b);
}
LL MultMod(LL a,LL b,LL n)//计算a*b%c(a和b直接相乘会超时)
{
a%=n;
b%=n;
LL ret=0;
while(b)
{
if(b&1)
{
ret+=a;
if(ret>=n) ret-=n;
}
a=a<<1;
if(a>=n) a-=n;
b=b>>1;
}
return ret;
}
LL PowMod(LL a,LL n,LL m)//计算a^n%m
{
LL ret=1;
a=a%m;
while(n>=1)
{
if(n&1)
ret=MultMod(ret,a,m);
a=MultMod(a,a,m);
n=n>>1;
}
return ret;
}
//根据这个定理,我们要计算a^(p-1) mod p是否等于1时,可以这样计算,设p-1=(2^t) * k。我们从a^k开始,不断将其平方直到得到a^(p-1)(因为p-1=(2^t) * k ,所以a^k平方t次可=p-1),一旦发现某次平方后mod p等于1了,那么说明符合了二次探测定理的逆否命题使用条件,立即检查x是否等于1或p-1,如果不是则可直接判定p为合数
bool Witness(LL a,LL n)
{
LL t=0,u=n-1;
while(!(u&1))
{
t++;
u/=2;
}
LL x0=PowMod(a,u,n);
for(int i=1; i<=t; i++)
{
LL x1=MultMod(x0,x0,n);
if(x1==1&&x0!=1&&x0!=(n-1))
return true;
x0=x1;
}
if(x0!=1)
return true;
return false;
}
bool Miller_Rabin(LL n,int t)
{
if(n==2) return true;
if((n&1)==0) return false;
srand(time(NULL));
for(int i=0; i<t; i++)
{
LL a=rand()%(n-1)+1;
if(Witness(a,n))
return false;
}
return true;
}
LL Pollard_Rho(LL n,LL c)
{
LL i=1,x=rand()%n,y=x,k=2;
while(1)
{
i++;
x=(MultMod(x,x,n)+c)%n;
LL d=gcd(y-x,n);
if(d!=1&&d!=n)
return d;
if(x==y)
return n;
if(i==k)
{
y=x;
k*=2;
}
}
}
void get_small(LL n,LL c)
{
if(n==1) return;
if(Miller_Rabin(n,TIME))
{
ans=min(n,ans);//一直取ans和n的最小值到最后时ans也就是最小素因子
return ;
}
LL p=n;
while(p>=n) p=Pollard_Rho(p,c--);
get_small(p,c);
get_small(n/p,c);
}
int main()
{
srand(time(NULL));
LL n;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%I64d",&n);
if(Miller_Rabin(n,TIME))
printf("Prime\n");
else
{
ans=n;
get_small(n,C);
printf("%I64d\n",ans);
}
}
return 0;
}