欧几里得算法及其扩展

欧几里得算法及其扩展

欧几里得算法(即辗转相除法, GCD),求 a 和 b 的最大公约数(greatest common divisor)。
在这里插入图片描述
参考代码:

int gcd(int a, int b){
	return (b == 0)? a:gcd(b, a%b);
}

裴蜀(贝祖)等式

对于任何整数 a , b 和它们的最大公倍数 d,关于未知数 x 和 y 的线性丢番图方程(称为裴蜀等式)。

ax + by = m

上述方程有整数解时当且仅当 m 是 d 的倍数

裴蜀等式有解时必然有无穷多个整数解,每组解 x,y 都称为裴蜀数

可用扩展欧几里得算法(Extended Euclidean algorithm)求得。
在这里插入图片描述
特别的,方程 ax + by = 1 有整数解当且仅当 a, b 互素。

拓展欧几里得算法

求 a, b 的最大公约数 m = gcd(a, b)的同时求出贝祖等式 ax + by = m 的一个解(x0, y0)。

设 k = a % b,则 a = bx + k = b * (a/b) +k ==> a%b = a - b * (a/b)

这里的除号 “/” 指的是计算机中不保留小数的除法。

我们要求的是 a * x + b * y = gcd = m

下一个状态是 b * x1 + (a%b) * y1 = gcd = m

把 a % b 代入:

gcd = b * x + (a - (a/b) * b) * y1

= b * x + a * y1 - (a/b) * b * y1

= a * y1 + b * (x1 - a/b *y1)

因此,得到递推式:x = y1 y = x1 - a/b * y1
在这里插入图片描述
上面的情况正好是 ax + by = gcd

若是求 ax + by = m 且 m % gcd = 0,则特解(x0, y0)需要乘以倍数 m/gcd。

通解:

x = x0 + (b/gcd) * t

y = y0 - (a/gcd) * t

如果想要得到 x > 0 的第一个解,则 b /= gcd x = (x0%b+b)%b

(此时 b 就是 x 的变化量)

(x % b 之后 |x0| < b,但无法保证 x > 0,所以要加上 b 保证 x > 0,但又不保证 < b,故再一次取模)

参考代码:

// 拓展欧几里得算法模板 
int extendGCD(int a, int b){
	// 最后一层的返回条件,此时a就是gcd 
	if(b == 0){
		x = 1;
		y = 0;
		return a;
	}
	// res的结果始终是gcd,不会改变 
	int res = extendGCD(b, a%b);
	// 进行过上一步之后,此时x和y已经是下一层的结果了 
	int x1 = x;
	x = y;
	y = x1 - a/b*y;
	return res;
}

【END】感谢观看

发布了44 篇原创文章 · 获赞 17 · 访问量 9117

猜你喜欢

转载自blog.csdn.net/qq_41765114/article/details/88384546