POJ 1181 大整数是否为素数以及求大整数的质因数-数论-(Miller_rabin+Pollard_rho)

题意:求一个整数是否是素数,如果不是,则输出它最小的质因数。

分析:

判断一个大整数是否为素数用Miller_rabin算法,求一个大整数的所有质因数用Pollard_rho算法。这题就是直接套模板。

另外这里的gcd和pow_mod不能用一般的方式,T了。代码里我注释掉的就是T了的写法。

代码:

#include<iostream>
#include<cmath>
#include<ctime>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
int t;
ll n,prim[1000];
ll ans;
int tot;
ll mul_mod(ll a,ll b,ll c)
{
	ll t=0;
	a%=c;
	b%=c;
	while(b){
		if(b&1){
			t=(t+a)%c;
		}
		a<<=1;
		a%=c;
		b>>=1;
	}
	return t;
}
//ll pow_mod(ll a,ll b,ll c)
//{
//	ll t=1;
//	while(b){
//		if(b&1) t=(t*a)%c;
//		b>>=1;
//		a=(a*a)%c;
//	}
//	return t;
//}
ll pow_mod(ll x,ll n,ll mod){
    if (n==1) return x%mod;
    int bit[90],k=0;
    while (n){
        bit[k++]=n&1;
        n>>=1;
    }
    ll ret=1;
    for (k=k-1;k>=0;k--){
        ret=mul_mod(ret,ret,mod);
        if (bit[k]==1) ret=mul_mod(ret,x,mod);
    }
    return ret;
}
bool check(ll a,ll n,ll x,ll t)
{
	ll ret=pow_mod(a,x,n);
	ll tmp=ret;
	for(int i=0;i<t;i++){
		ret=mul_mod(ret,ret,n);
		if(ret==1&&tmp!=1&&tmp!=n-1) return true;
		tmp=ret;
	}
	if(ret!=1) return true;
	return false;
}
bool Miller_rabin(ll n)
{
	ll x=n-1,t=0;
	while((x&1)==0){
		x>>=1;
		t++;
	}
	int ok=1;
	if(t>=1&&(x&1)){
		for(int i=0;i<20;i++){
			ll a=rand()%(n-1)+1;
			if(check(a,n,x,t)){
				ok=1;break;
			}
			ok=0;
		}
	}
	if(!ok||n==2) return false;
	return true;
}
//ll gcd(ll a,ll b)
//{
//	if(b==0) return a;
//	return gcd(b,a%b);
//}
ll gcd(ll a,ll b){
    if (a==0) return 1;
    if (a<0) return gcd(-a,b);
    while (b){
        ll t=a%b; a=b; b=t;
    }
    return a;
}
ll Pollard_rho(ll x,ll c)
{
	ll i=1,k=2;
	ll x0=rand()%x,y=x0;
	while(1){
		i++;
		x0=(mul_mod(x0,x0,x)+c)%x;
		ll d=gcd(y-x0,x);
		if(d>1&&d<x) return d;
		if(y==x0) return x;
		if(i==k){
			y=x0;
			k+=k;
		}
	}
}
void findfac(ll n)
{
	if(!Miller_rabin(n)){
		prim[tot++]=n;
		return;
	}
	ll p=n;
	while(p>=n) p=Pollard_rho(p,rand()%(n-1)+1);
	findfac(p);
	findfac(n/p);
}
int main()
{
	srand(time(NULL));
	scanf("%d",&t);
	while(t--){
		scanf("%lld",&n);
		if(!Miller_rabin(n)){
			printf("Prime\n");
			continue;
		}
		tot=0;
		findfac(n);
		ans=prim[0];
		for(int i=1;i<tot;i++){
			ans=min(ans,prim[i]);
		}
		printf("%lld\n",ans);
	}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-28 21:18:39

POJ 1181 大整数是否为素数以及求大整数的质因数-数论-(Miller_rabin+Pollard_rho)的相关文章

数论快速入门(同余、扩展欧几里德、中国剩余定理、大素数测定和整数分解、素数三种筛法、欧拉函数以及各种模板)

数学渣渣愉快的玩了一把数论,来总结一下几种常用的算法入门,不过鶸也是刚刚入门, 所以也只是粗略的记录下原理,贴下模板,以及入门题目(感受下模板怎么用的) (PS:文中蓝色字体都可以点进去查看百度原文) 附赠数论入门训练专题:点我打开专题(题目顺序基本正常,用以配套数论入门) 一.同余定理 简单粗暴的说就是:若 a-b == m 那么 a%m == b%m 这个模运算性质一眼看出...直接上入门水题: Reduced ID Numbers 附AC代码(这个也没啥模板....知道就好) #inclu

数论 - Miller_Rabin素数测试 + pollard_rho算法分解质因数 ---- poj 1811 : Prime Test

Prime Test Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 29046   Accepted: 7342 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

经典算法之判断一个整数是否为素数

经典算法之判断一个整数是否为素数 1 /** 2 判断一个数是否为素数 如: 3 输入: 任意一个数 12 4 输出: 1或0(1表示为素数) 0 5 */ 6 /**************被称为笨蛋的做法************/ 7 #include <stdio.h> 8 9 int main() 10 { 11 12 int i,n; //i为计数数,n为存储用户输入的数 13 14 do //循环检测用户输入的数据>0为合法 15 scanf("%d",&

POJ 2262 Goldbach&#39;s Conjecture (求解素数的一般筛和线性筛)

Goldbach's Conjecture Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 40944   Accepted: 15664 Description In 1742, Christian Goldbach, a German amateur mathematician, sent a letter to Leonhard Euler in which he made the following conject

poj 2478 Farey Sequence(基于素数筛法求欧拉函数)

http://poj.org/problem?id=2478 求欧拉函数的模板. 初涉欧拉函数,先学一学它基本的性质. 1.欧拉函数是求小于n且和n互质(包括1)的正整数的个数.记为φ(n). 2.欧拉定理:若a与n互质,那么有a^φ(n) ≡ 1(mod n),经常用于求幂的模. 3.若p是一个质数,那么φ(p) = p-1,注意φ(1) = 1. 4.欧拉函数是积性函数: 若m与n互质,那么φ(nm) = φ(n) * φ(m). 若n = p^k且p为质数,那么φ(n) = p^k - p

[算法]:分治法-求大整数相乘

#问题大整数相乘 #思路说明 对于大整数计算,一般都要用某种方法转化,否则会溢出.但是python无此担忧了. Python支持**"无限精度"的整数,**一般情况下不用考虑整数溢出的问题,而且Python Int类型与任意精度的Long整数类可以无缝转换,超过Int 范围的情况都将转换成Long类型. 例如: >>> 2899887676637907866*1788778992788348277389943 51872581574157002360341697913

POJ 2262 Goldbach&#39;s Conjecture(素数筛选法)

Description In 1742, Christian Goldbach, a German amateur mathematician, sent a letter to Leonhard Euler in which he made the following conjecture: Every even number greater than 4 can be written as the sum of two odd prime numbers. For example: 8 =

求指定整数范围内的素数之和

//求指定整数范围内的素数之和int getSumResult(int start,int end){ int i,j; int flag=0; int result=0; if(start<0||end <0) { lr_output_message("开始值.结束值需要为正整数"); exit(-1); } else if(start>=end) { lr_output_message("开始值需要<结束值"); exit(-1); }

判断一个整数是否为素数(质数)

//判断一个整数是否为素数(质数)//质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数,这样的数称为质数#include <stdio.h>int main(){ int n, i, flag = 0; printf("请输入一个正整数:"); scanf("%d", &n); for (i = 2; i <= n / 2; ++i) { //如果满足以下的条件,他就不是素数 if (n%i == 0) { flag = 1;