题目来源:http://poj.org/problem?id=1811
这题是miller_rabbin素数测试 + pollar_rho
所用的miller_rabbin貌似不止用了费马小定理,还用了一个不知名的定理,但如果像某些写法中,把miller_rabbin函数中的if (!Judge(a,n)) return 0;
改成if (modular_exp(a,n-1,n)!=1) return 0;
则会直接WA,虽然之前水CodeVS2849时这么写就没有问题。。
pollard rho算法思想可以在Pollard rho算法详解看一下
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
int T;ll n,minx;
ll multi (ll x,ll y,ll mod) {
ll ans=0;
x%=mod;
for (;y;y>>=1,x=(x<<1)%mod)
if (y&1) ans=(ans+x)%mod;
return ((ans+mod)%mod);
}
ll modular_exp (ll x,ll p,ll mod) {
ll ans=1;
x%=mod;
for (;p;p>>=1,x=multi(x,x,mod))
if (p&1) ans=multi(ans,x,mod);
return ((ans+mod)%mod);
}
bool Judge (ll a,ll n)
{
ll d=n-1;
while (!(d&1)) d>>=1;
ll t=modular_exp(a,d,n);
while (d!=n-1&&t!=1&&t!=n-1)
t=multi(t,t,n),d<<=1;
return t==n-1||d&1;
}
bool miller_rabbin (ll n) {
if (n==2) return 1;
if (n<2||!(n&1)) return 0;
ll a;
for (int i=0;i<10;i++) {
a=rand()%(n-2)+2;
if (!Judge(a,n)) return 0;
}
return 1;
}
ll gcd (ll a,ll b) {
if (a==0) return 1;//?
if (!b) return a;
return gcd(b,a%b);
}
ll pollard_rho (ll a,ll c) {
ll i=1,k=2,x=rand()%a;ll y=x;
while (1) {
i++; x=(multi(x,x,a)+c)%a;
ll d=gcd((ll)fabs(y-x),a);
if (d!=1&&d!=a) return d;
if (y==x) return a;
if (i==k) y=x,k<<=1;
}
}
void findfac (ll n) {
if (n==1) return ;//
if (miller_rabbin(n)) {
minx=min(minx,n);
return ;
}
ll p=n;
while (p>=n) p=pollard_rho(p,rand()%(n-1)+1);
findfac(p);findfac(n/p);
}
int main () {
srand(233);
scanf("%d",&T);
while (T--) {
scanf("%lld",&n);minx=n;
if (miller_rabbin(n)) puts("Prime");
else {
findfac(n);
printf("%lld\n",minx);
}
}
return 0;
}