扩展欧几里得算法

一、ax+by=gcd(a,b)的求解

问题:给定a,b两个非零整数,求满足ax+by=gcd(a,b)的整数解x、y,其中gcd(a,b)是a和b的最大公约数。

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

在求最大公约数的算法中,当到达递归边界b=0, a=gcd时,有(x1, y1)=(1,0)使ax1+by1=gcd(a,b)成立,假设bx2+(a%b)y2=gcd(b,a%b),那么如果能找到(x1,y1)与(x2,y2)的关系,就可以用(x1, y1)=(1,0)为边界,在不断退出递归的过程中最终得到a=a0, b=b0时ax+by=gcd(a,b)的解(设a0, b0为a, b的初始值)。

{ a x 1 + b y 1 = g c d ( a , b ) b x 2 + ( a % b ) y 2 = g c d ( b , a % b ) g c d ( a , b ) = g c d ( b , a % b ) \left\{ \begin{aligned} &ax_1+by_1=gcd(a,b)\\ &bx_2+(a\%b)y_2=gcd(b,a\%b)\\ &gcd(a,b)=gcd(b,a\%b) \end{aligned} \right. ax1+by1=gcd(a,b)bx2+(a%b)y2=gcd(b,a%b)gcd(a,b)=gcd(b,a%b)
得:ax1+by1=bx2+(a%b)y2,又因为a%b=a-(a/b)*b(其中a/b取整数),带入整理可以得到:ax1+by1=ay2+b[x2-(a/b)y2]
因此有:
{ x 1 = y 2 y 1 = x 2 − ( a / b ) y 2 \left\{ \begin{aligned} x_1&=y_2\\ y_1 &=x_2-(a/b)y_2 \end{aligned} \right. {x1y1=y2=x2(a/b)y2
因此,求一个特解(x0,y0)的算法如下:

void exgcd(int a,int b,int &x,int &y){
{
	if(b==0){
		x=1;
		y=0;
	}
	exgcd(b,a%b,x,y)
	int temp=x;
	x=y;
	y=temp-(a/b)*y;
}

显然,ax+by=gcd(a,b)可能有多个解,假设通解为
{ x = x 0 + s 1 y = y 0 + s 2 \left\{ \begin{aligned} &x=x_0+s_1\\ &y=y_0+s_2 \end{aligned} \right. {x=x0+s1y=y0+s2

{ a x 0 + b y 0 = g c d ( a , b ) a x + b y = g c d ( a , b ) \left\{ \begin{aligned} &ax_0+by_0=gcd(a,b)\\ &ax+by=gcd(a,b) \end{aligned} \right. {ax0+by0=gcd(a,b)ax+by=gcd(a,b)
得:as1+bs2=0,所以s1/s2=-b/a=-(b/gcd)/(a/gcd),因为b/gcd与a/gcd互质,所以s1与s2最小分别为b/gcd、-a/gcd(正负反过来也可以),这就得到了ax+by=gcd(a,b)的通解:
{ x = x 0 + K ∗ b / g c d y = y 0 − K ∗ a / g c d \left\{ \begin{aligned} &x=x_0+K*b/gcd\\ &y=y_0-K*a/gcd \end{aligned} \right. {x=x0+Kb/gcdy=y0Ka/gcd
**PS:**由任意一组解得到最小非负整数解,以x为例,因为x%gcd可能为负,所以最小非负整数解为(x%gcd+gcd)%gcd.

二、ax+by=c的求解

ax+by=c有解的充要条件是:c%gcd=0(我只知道ax+by=c有解一定可以得到c%gcd=0,因为a和b都是gcd的倍数,所以c必须也是)。
在ax+by=gcd(a,b)两边同乘c/gcd得到a(cx/gcd)+b(cy/gcd)=c. 因此,将ax+by=gcd(a,b)的特解(x0, y0)乘上c/gcd就得到了ax+by=c的特解,显然,ax+by=gcd(a,b)的通解乘上c/gcd也是ax+by=c的解(Kb/gcd变为Kb/gcd²,Ka/gcd变为Ka/gcd²);但是,按照上面求通解的步骤:
{ x = c x 0 g c d + s 1 y = c y 0 g c d + s 2 \left\{ \begin{aligned} &x=\frac{cx_0}{gcd}+s_1\\ &y=\frac{cy_0}{gcd}+s_2 \end{aligned} \right. x=gcdcx0+s1y=gcdcy0+s2
{ a c x 0 g c d + b c y 0 g c d = c a x + b y = c \left\{ \begin{aligned} &a\frac{cx_0}{gcd}+b\frac{cy_0}{gcd}=c\\ &ax+by=c \end{aligned} \right. agcdcx0+bgcdcy0=cax+by=c
依然得到s1/s2=-b/a=-(b/gcd)/(a/gcd),所以通解为:
{ x = c x 0 g c d + K ∗ b / g c d y = c y 0 g c d − K ∗ a / g c d \left\{ \begin{aligned} &x=\frac{cx_0}{gcd}+K*b/gcd\\ &y=\frac{cy_0}{gcd}-K*a/gcd \end{aligned} \right. x=gcdcx0+Kb/gcdy=gcdcy0Ka/gcd

三、ax≡c(modm)求解

如果(a-b)%m=0,那么a与b模m同余,写为a≡b(modm)。
因为ax≡c(modm),所以(ax-c)%m=0,即ax-c=my,即ax-my=c,这就变成了ax+by=c求解,其中b=-m,只需要求x的解就可以了。

参考:《算法笔记》5.7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值