算法学习笔记-exgcd

前言:

exgcd,顾名思义,是 gcd 的一种扩展。gcd 是求最大公因数,所用到的是辗转相除法,基于 gcd(a,b)=gcd(b,amodb)(a>b) 的原理,在学习 exgcd 前,请确保已掌握 gcd ,并懂得一点数学归纳法。如果您已掌握这些前置知识,请开始学习。

例题:

先看这样一道题,给定整数 a,b ,求 x,y 使得 ax+by=1

性质:

性质1:

这显然是一道数学题(废话),考虑将原式根据乘法分配律转换为 gcd(a,b)×(agcd(a,b)x+bgcd(a,b)y)=1。而如果两个整数乘积为 1,则他们一定为 1,因此 gcd(a,b)=1 ,换句话说,a,b 互质。

综上所述,我们得出性质,若原方程有解,当且仅当 a,b 互质。

性质2:

这个性质就比较简单,它实际上是类似于递归边界的东西,并不需要怎么推导。考虑当 a=1,b=0 ,原方程有一组解为 x=1,y=0

推导:

先看原式:ax+by=1
m=amodbk=ab,则 a=bk+m。(其实就是余数和商)。
设有一个和原式一样的方程 xm+yb=1

根据 m 的定义,转换为 x(akb)+yb=1

将式子打开,变为 xaxkb+yb=1

合并同类项,变为 xa(ykx)b=1

可以发现一个神奇的事情,转化后的方程与原方程本质是一样的!唯一变化的只有 xy 的值。也就是说,若 xamodb+yb=1 有解,那么 ax+by=1 也一定有解。而且这个解就是 x=x, y=ykx(将所推方程代入)。而根据 gcd 的写法,两个互质的数到递归边界时一定是 a=1,b=0。因为 a=1,b=0 的情况是有解的,所以 gcd(a,b)=1 也是有解的,这也进一步证明了上面的性质。

如果你到这里都听懂了,那么下面的问题就很简单了,只需将 x,y 代入下面推出来的式子即可。

结论:

通过以上推导,可以得出:

  1. 原方程有解当且仅当 gcd(a,b)==1
  2. 原方程解为 {x=1y=0a=1,b=0x=xy=ykx(xamodb+yb=1,k=ab)otherwise

实现:

exgcd 模版见下(递归):

点击查看代码
void exgcd(int a, int b, int &x, int &y)
{
	if(a == 1 && b == 0)//边界 
	{
		x = 1, y = 0;
		return ;
	}
	exgcd(b, a % b, y, x);
	//这里之所以要交换x和y的位置,是因为b与a%b交换了,根据公式要把x,y也换过去 
	y = y - a / b * x;//按照公式赋值,由于是引用,所以x的值已经更改了。 
}

总结:

第一次学 exgcd 时,刚开始看到结论十分蒙,等到搞清楚证明时觉得这个证明妙不可言。笔者认为,学习 exgcd 应不仅只会背代码,更要明白证明的过程,最好自己手推一遍。因为证明不仅是解决之后的许多与 exgcd 的题有关,更能扩展思维,对数论有很大帮助。

鉴于笔者也是蒟蒻,文中给出的部分推导过程与表述可能不严谨,欢迎大佬在评论区指出。
同时如果您对文章内容有不理解的地方,欢迎随时提问。

posted @   zhangxiao666  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示