Pollard_rho随机算法+Miller_rabin算法-大整数质因数分解

版权声明:希望大家读懂代码,而不是复制粘贴提交 https://blog.csdn.net/pythonbanana/article/details/82904066

Pollard_rho算法详解传送门
素数判定Miller_Rabin 算法详解传送门
随机算法Pollard_rho分解大整数质因数,随机算法Miller_rabin素数判定。
我理解了一个下午还有一个晚上(特别在debug花费了2个小时),结果犯了一个低级隐形错误,我照着模板改了好几次,都没改出来。最后改出来,心里都崩溃了。
最终是两个if的顺序弄反了。但是我白这两个写反了。
为了避免这种条件(前面的条件会对后面有隐含作用),比如n==2,与后面的n % 2 == 0,说明n != 2 && n % 2 == 0,所以 不如把那个条件写上(n != 2).

if(n == 2){//这两个顺序不能变 ,因为这个条件,会被包含在第二个判断里面但是要先判断 
	return true;
}
if(n < 2 || n % 2 == 0){//这个判断必须在后面,想哭 
	return false;
}
#include<iostream>
#include<cstdio>
#include<map>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define per(i,a,b) for(int i=a;i<=b;i++)

typedef long long LL;

const int times = 20;
map<LL,int> mp;
int number = 0;

LL Random(LL n){
	return ((double)rand() / RAND_MAX * n + 0.5);
}
LL q_mul(LL a,LL b,LL mod){
	LL ans = 0;
	while(b > 0){
		if(b & 1){
			ans = (ans + a) % mod;
		}
		b >>= 1;
		//b /= 2;
		a = (a + a) % mod;
	}
	return ans;
}
LL q_pow(LL a,LL b,LL mod){
	LL ans = 1;
	while(b > 0){
		if(b & 1){
			ans = q_mul(ans,a,mod);
		}
		b >>= 1;
		//b /= 2;
		a = q_mul(a,a,mod);
	}
	return ans;
}
LL gcd(LL a,LL b){
	return (b == 0) ? a : gcd(b,a % b);

}
bool witness(LL a,LL n){//Miller_rbin()算法的精华所在 
	
	LL temp = n - 1;//是n-1 
	int j = 0;
	while(temp % 2 == 0){
		temp /= 2;
		j++;	
	}
	LL x = q_pow(a,temp,n);//计算a^r
	if(x == 1 || x == n-1 ){
		return true;
	} 
	while(j--){
		x = q_mul(x,x,n);
		if(x == n-1){
			return true;
		}
	}
	return false;
}
bool Miller_rbin(LL n){
	
	if(n == 2){//这两个顺序不能变 ,因为这个条件,会被包含在第二个判断里面但是要先判断 
		return true;
	}
	if(n < 2 || n % 2 == 0){//这个判断必须在后面,想哭 
		return false;
	}
	per(i,1,times){
		LL a = Random(n - 2) + 1;
		if(witness(a,n) == false){
			return false;
		}
	}
	
	return true;
}
LL pollard_rho(LL n,LL c){
	LL i = 1,k = 2;
	LL x = Random(n-1) + 1;
	LL y = x;
	
	while(true){
		i++;
		x = (q_mul(x,x,n) + c) % n ;
		LL d = gcd(y-x,n);
		if(1 < d && d < n){
			return d;
		}
		if(y == x){
			return n;
		}
		if(i == k){//一种不清楚的优化 
			y = x;
			k <<= 1;
		}
	}
} 
void find(LL n,LL c){//c是随机因子 
	if(n == 1){
		return ;
	}
	if(Miller_rbin(n)){
		number++;
		mp[n]++;
		return ;
	}
	
	LL p = n;
	while(p >= n){
		p = pollard_rho(p,c--);
	}
	find(p,c);	
	find(n/p,c);
} 
int main(){
	#ifndef ONLINE_JUDGE
		//freopen("a.txt","r",stdin);
	#endif
	LL n = 0; 
	while(~scanf("%I64d",&n)){
		number = 0;
		mp.clear();
		LL mi = 2137342;
		find(n, mi);
		printf("%I64d = ",n);
		if(mp.empty()){
			printf("%I64d\n",n);
		}
		map<LL,int>::iterator it ;
		for(it = mp.begin();it != mp.end();){
			printf("%I64d^%d",it->first,it->second);
			if((++it) != mp.end()){
				printf(" * ");
			}
		}
		printf("\n");
	}
	
	return 0; 
}

猜你喜欢

转载自blog.csdn.net/pythonbanana/article/details/82904066