http://poj.org/problem?id=1811
先用Miller_Rabin算法进行素数判断,再用Pollard_rho分解素因子。
今天做TC时,遇到一道大素数判定和质因子分解的模板题。想到了质因子分解,但没想到用这个模板。赛后,还是自己理解一遍,然后手敲吧。。
#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define _LL __int64
#define eps 1e-12
#define PI acos(-1.0)
#define C 240
#define S 20
using namespace std;
LL fac[100];
int tol;
LL gcd(LL a, LL b)
{
if(a == 0)
return 1;
if(a < 0)
return gcd(-a,b);
if(b == 0)
return a;
return gcd(b,a%b);
}
LL MultMod(LL a, LL b, LL n)
{
a %= n;
b %= n;
LL ret = 0;
while(b)
{
if(b&1)
{
ret += a;
if(ret >= n)
ret -= n;
}
a <<= 1;
if(a >= n)
a -= n;
b >>= 1;
}
return ret;
}
LL PowMod(LL a, LL n, LL m)
{
LL ret = 1;
a %= m;
while(n)
{
if(n&1)
ret = MultMod(ret,a,m);
a = MultMod(a,a,m);
n >>= 1;
}
return ret;
}
/// 大素数判定
bool Witness(LL a, LL n)
{
LL t = 0;
LL u = n-1;
while(!(u&1))
{
t++;
u = 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)
{
if(n == 2)
return true;
if((n&1) == 0)
return false;
//srand(time(NULL));
for(int i = 0; i < S; i++)
{
LL a = rand()%(n-1) + 1;
if(Witness(a,n))
return false;
}
return true;
}
///质因子分解
LL Pollar_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 = k*2;
}
}
}
void get_small(LL n, LL c)
{
if(n == 1)
return;
if(Miller_Rabin(n))
{
fac[tol++] = n;
return;
}
LL p = n;
while(p >= n)
p = Pollar_Rho(p,c--);
get_small(p,c);
get_small(n/p,c);
}
int main()
{
int test;
LL n;
scanf("%d",&test);
while(test--)
{
scanf("%lld",&n);
if(Miller_Rabin(n))
{
printf("Prime\n");
continue;
}
tol = 0;
get_small(n,C);
LL ans = fac[0];
for(int i = 1; i < tol; i++)
ans = min(ans,fac[i]);
printf("%lld\n",ans);
}
return 0;
}