您的位置:首页 > 其它

poj 1181(大数判素数 ,分解)

2013-05-28 16:29 387 查看
//miller_rabin 判断一个大数是否是素数
//pollard_rho 大数因子分解
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

#define LL long long
const LL Max = (LL) 1 << 62;
LL p[10]={2,3,5,7,11,13,17,19,23,29};

//计算a*b%n
inline LL multi_mod(LL a,LL b,LL mod)
{
LL sum=0;
while(b)
{
if(b&1)    sum = (sum + a) % mod;
a <<= 1;
b >>= 1;
if (a >= mod) a %= mod;
}
return sum;
}

//计算a^b%n;
inline LL quick_mod(LL a,LL b,LL mod)
{
LL sum = 1;
while(b)
{
if(b & 1) sum = multi_mod(sum, a, mod);
a = multi_mod(a, a, mod);
b >>= 1;
}
return sum;
}

bool miller_rabin(LL n)
{
LL u,m,buf;
int k = 0;
//将n分解为m*2^k
if(n==2)   return true;
if(n<2 || !(n&1))    return false;
m = n - 1;
while(!(m&1))
k++,m >>= 1;
for(int i = 0; i < 9; ++i)
{
if(p[i] >= n) return true;
u = quick_mod(p[i], m, n);
if(u==1) continue;
for(int j = 0; j < k; ++j)
{
buf = multi_mod(u, u, n);
if(buf == 1 && u != 1 && u != n - 1)
return false;
u = buf;
}
//如果p[i]^(n-1)%n!=1那么n为合数
if(u - 1) return false;
}
return true;
}

LL gcd(LL a, LL b)
{
return b == 0 ? a: gcd(b, a%b);
}
//寻找n的一个因子,该因子并不一定是最小的,所以下面要二分查找最小的那个因子
LL pollard(LL n )
{
LL x,y,c=0,d,i=1,k=2;
while(c==0 || c==2 ) c = abs( rand())%(n-1) + 1;
x = y = (rand( )%( n-1 )) + 1;
do
{
i++;
d = gcd( y + n - x, n );
if( d >1 && d < n )
return d;
if( i == k )
{
y = x; k <<= 1;
}
x = (multi_mod( x , x, n )+n-c )%n;
}while( x != y );
return n;
}

LL pollard_min(LL n)
{
LL p,a,b=Max;
if(n==1)    return Max;
if(miller_rabin(n))    return n;
p = pollard(n);
a = pollard_min(p);//二分查找
b = pollard_min(n / p);
return a < b ? a : b;
}

int main(void)
{
LL T;
LL n;
scanf("%lld",&T);
while(T--)
{
scanf("%lld",&n);
if(miller_rabin(n))
{
puts("Prime");
}
else printf("%lld\n",pollard_min(n));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: