poj1811(Miller-Rabin(素数测试)与Pollard rho(整数的因子分解))

地址:http://poj.org/problem?id=1811

Prime Test
Time Limit: 6000MS Memory Limit: 65536K
Total Submissions: 26694 Accepted: 6587
Case Time Limit: 4000MS

Description

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

题意:看一个数是不是素数,不是的话输出其最小素数因子。

网上找的模版(http://xingyezhi.diandian.com/post/2012-02-26/15529645

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX (pow(2.0,60))
#define LL __int64
LL MIN;
LL gcd(LL a,LL b)
{
	if(b==0)
		return a;
	else return gcd(b,a%b);
}
LL num_mul(LL a,LL b,LL n)
{
	LL s=0;a%=n;
	while(b)
	{
		if(b&1)
		{
			s+=a;
			if(s>n) s-=n;
		}
		a=a<<1;
		if(a>n) a-=n;
		b=b>>1;
	}
	return s;
}
LL num_quar(LL a,LL b,LL n)
{
	LL s=1;
	a%=n;
	while(b)
	{
		if(b&1)
			s=num_mul(s,a,n);
		a=num_mul(a,a,n);
		b=b>>1;
	}
	return s;
}
bool miller_test(LL a,LL n)
{
	LL x,y,m;
	int i,j=0;
	m=n-1;x=0;
	while(m%2==0)
	{
		j++;m=m>>1;
	}
	x=num_quar(a,m,n);
	for(i=1;i<=j;i++)
	{
		y=num_quar(x,2,n);
		if((y==1)&&(x!=1)&&(x!=n-1))
			return true;
		x=y;
	}
	if(y!=1) return true;
	return false;
}
bool times_miller(int times,LL n)
{
	LL a;
	int i;
	if(n==1) return false;
	if(n==2) return true;
	if(n%2==0) return false;
	srand(time(NULL));
	for(i=1;i<=times;i++)
	{
		a=rand()%(n-1)+1;
		if(miller_test(a,n))
			return false;
	}
	return true;
}
LL pollard(LL n,int c)
{
	LL i,k,x,y,d;
	srand(time(NULL));
	i=1;k=2;
	x=rand()%n;y=x;
	while(true)
	{
		i++;
		x=(num_mul(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=k<<1;
		}
	}
}
void get_small(LL n,int c)
{
	LL m;
	if(n==1) return ;
	if(times_miller(12,n))
	{
		if(n<MIN)
			MIN=n;
		return ;
	}
	m=n;
	while(m==n)
		m=pollard(n, c--);
	get_small(m,c);
	get_small(n/m,c);
}
int main()
{
	LL m,t;
	scanf("%I64d",&t);
	while(t--)
	{
		scanf("%I64d",&m);
		if(times_miller(12,m))
			puts("Prime");
		else
		{
			MIN=MAX;
			get_small(m,240);
			printf("%I64d\n",MIN);
		}
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值