⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 miller_rabin and pollard_rho.cpp

📁 数值计算的例子和参考书籍
💻 CPP
字号:
//miller_rabin大数检测+Pollard P素因子分解
//输入 a<2^63
//加大MAX 可以保证分解的成功率
#include <stdlib.h>
#include <stdio.h>

typedef unsigned __int64 u64;

#define MAX 100
#define MAXN 30

u64 len, dig, limit;
u64 mod(u64 a, u64 b, u64 n)
{
	if(!a) return 0;
	else return (((a & dig) * b) % n + (mod(a >> len, b, n) << len) % n) % n;
}

u64 by(u64 a, u64 b, u64 n)
{
	u64 p;
	p = 8, len = 61;
	while(p < n)
	{
		p <<= 4;
		len -= 4;
	}
	dig = ((limit / p) << 1) - 1; //动态划分段
	return mod(a, b, n);
}

u64 random(void)
{
	u64 a;
	a = rand();
	a *= rand();
	a *= rand();
	a *= rand();
	return a;
}

//Miller_Rabin
u64 square_multiply(u64 x, u64 c, u64 n)
{
	u64 z = 1;
	while(c)
	{
		if(c % 2 == 1) z = by(z, x, n);
		x = by(x,x,n);
		c = (c >> 1);
	}
	return z;
}

bool Miller_Rabin(u64 n)
{
	if(n < 2) return false;
	if(n == 2) return true;
	if(!(n & 1)) return false;
	u64 k = 0, i, j, m, a;
	m = n - 1;
	while(m % 2 == 0) m = (m >> 1), k++;
	for(i = 0; i < MAX; i++)
	{
		a = square_multiply(random() % (n - 1) + 1, m, n);//平方乘
		if(a == 1) continue;
		for(j = 0; j < k; j++)
		{
			if(a == n - 1) break;
			a = by(a, a, n);
		}
		if(j < k) continue;
		return false ;
	}
	return true;
}

//Pollard p,只找出一个因子。
u64 gcd(u64 a, u64 b)
{
	return b == 0 ? a : gcd(b, a % b);
}

//用公式f(x) = x^2 + 1检验碰撞。
u64 f(u64 x, u64 n)
{
	return (by(x, x, n) + 1) % n;
}

//分解不到,return 0
u64 Pollard(u64 n)
{
	if(n <= 2) return 0;
	if(!(n & 1)) return 2; //必不可少
	u64 i, p, x, xx;
	for(i = 1; i < MAX; i++)
	{
		x = random() % n; //或者直接用 x = i
		xx = f(x, n);
		p = gcd((xx + n - x) % n , n);
		while(p == 1)
		{
			x = f(x, n);
			xx = f(f(xx, n), n);
			p = gcd((xx + n - x) % n, n) % n;
		}
		if(p)return p;
	}
	return 0;
}

/////////////////////////////////////////////////////////
u64 factor[MAXN], m;
/////////////////////////////////////////////////////
//分解质数因子
u64 prime(u64 a)
{
	if(Miller_Rabin(a)) return 0;
	u64 t = Pollard(a), p;
	if(p = prime(t)) return p;
	else return t;
}

int main(void)
{
	u64 l, a, t;
	limit = 1;
	limit = limit << 63; //动态化分段使用
	while(scanf("%I64u", &a) != EOF)
	{
		m = 0;
		while(a > 1)
		{
			if(Miller_Rabin(a)) break;
			t = prime(a);
			factor[m++] = t;
			a /= t;
		}
		if(a > 0) factor[m++] = a;
		for(l = 0; l < m; l++)
			printf("%I64u\n", factor[l]);
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -