存抄模板,Millar-Rabin算法原理看懂了,Pollard_rho表示找不到证明,只能照着模板敲了一遍。
ACcode:
#include<cstdio>
#include<cstdlib>
#include<iostream>
typedef long long LL;
#define MAX ((LL)1<<61)
const int CT=201;
const int Times=50;
LL min_factor;
LL multi(LL aa,LL bb,LL mod)
{
LL res=0;
while (bb>0)
{
if (bb&1) res=(res+aa)%mod;
bb>>=1;
aa=(aa<<1)%mod;
}
return res;
}
LL quick_mod(LL aa,LL bb,LL mod)
{
LL res=1;
aa%=mod;
while (bb>0)
{
if (bb&1) res=multi(res,aa,mod);
bb>>=1;
aa=multi(aa,aa,mod);
}
return res;
}
int judge(LL aa,LL n)
{
int c=0;
LL bb=n-1;
while (!(bb&1)) c++,bb>>=1;
LL ans=quick_mod(aa,bb,n);
if (ans==1||ans==(n-1)) return 0;
for (int i=0;i<c;i++)
{
ans=multi(ans,ans,n);
if (ans==n-1) return 0;
}
return 1;
}
int Miller_Rabin(LL n)
{
LL rd;
if (n<2) return 0;
if (n<4) return 1;
if (!(n&1)) return 0;
for (int i=0;i<Times;i++)
{
rd=(LL)((double)rand()/RAND_MAX*(n-2)+2);
if (judge(rd,n)) return 0;
}
return 1;
}
LL gcd (LL aa,LL bb)
{
return bb==0?aa:gcd(bb,aa%bb);
}
LL pollard_rho(LL n,int c)
{
LL d,x,y,i=1,k=2;
y=x=(LL)((double)rand()/RAND_MAX*(n-1)+1);
while (1)
{
i++;
x=(multi(x,x,n)+c)%n;
d=gcd(y-x,n);
if (d>1&&d<n) return d;
if (y==x) return n;
if (i>=k)
{
y=x;
k<<=1;
}
}
}
void Fin(LL n,int c)
{
if (n==1) return ;
if (Miller_Rabin(n))
{
min_factor=n<min_factor?n:min_factor;
return ;
}
LL k=n;
while (k>=n) k=pollard_rho(k,c--);
Fin(k,c);
Fin(n/k,c);
}
int main()
{
int T;
LL n;
scanf("%d",&T);
while (T--)
{
scanf("%I64d",&n);
if (Miller_Rabin(n))
printf("Prime\n");
else
{
min_factor=MAX;
Fin(n,CT);
printf("%I64d\n",min_factor);
}
}
return 0;
}