算法笔记:扩展欧几里得算法

1.引入

扩展欧几里得算法是欧几里得算法(又叫辗转相除法)的扩展。除了计算a、b两个整数的最大公约数,此算法还能找到整数x、y(其中一个很可能是负数)。通常谈到最大公因子时, 我们都会提到一个非常基本的事实: 给予二整数 a 与 b, 必存在有整数 x 与 y 使得ax + by = gcd(a,b)。有两个数a,b,对它们进行辗转相除法,可得它们的最大公约数——这是众所周知的。然后,收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解。

各位应该会记得中学接触的一个问题:给出整数a,b,n,问方程ax+by=n什么时候有整数解,如何求所有的整数解?

其实有解的充分必要条件是gcd(a,b)可以整除n,解释如下:
我们首先令
a=gcd(a,b)*a1,b=gcd(a,b) * b2
则有ax+by=gcd(a,b )*a1x+gcd(a,b) * b1y=gcd(a,b)(a1x+b2y)=n
那如果a1,b1,x,y都为整数的话,那么n/gcd(a,b)也一定是整数,所以n必须是gcd(a,b)的倍数才会有整数解。

例如
4x+6y=8,2x+3y=4有整数解,4x+6y=7就没有整数解

如果确定有解,一种解题方法就是就是先找出一个解(x0,y0),那么通解公式就是如下:
x=x0+bt
y=y0-at ( t是任意整数)
所以这个问题就转换为如何求(x0,y0)了,利用扩展欧几里得算法就可以求出这个特解

2.扩展欧几里得算法

当方程满足ax+by=gcd(a,b)时,可以用扩展欧几里得算法求(x0,y0),程序如下:

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

有时候为了简化描述,在ax+by=gcd(a,b)两边除以gcd(a,b),得到cx+dy=1,其中c=a/gcd(a,b),d=b/gcd(a,b)。很明显,c和d是互质的,cx+dy=1的通解为
x=x0+dt;
y=y0-ct (t是任意整数)

扩展

1.求任意方程ax+by=n的一个整数解

用扩展欧几里得算法求解ax+by=gcd(a,b)后,利用它可以进一步解任意方程ax+by=n得到一个整数解,其步骤如下:
(1)判断方程ax+by=n是否存在整数解,有解的条件是gcd(a,b)可以整除n
(2)用扩展欧几里得算法求ax+by=gcd(a,b)的一个解(x0,y0)
(3) 在ax0+by0=gcd(a,b)两边同时乘以n/gcd(a,b),得:
ax0n/gcd(a,b)+by0n/gcd(a,b)=n
(4)对照ax+by=n,得到它的一个解(x,y)是:
x=x0n/gcd(a,b)
y=y0n/gcd(a,b)

应用场合

扩展欧几里得算法是一个很有用的工具,在竞赛题目中常用与以下场合:
(1)求解不定方程
(2)求解模的逆元
(3)求解同余方程
虽然用扩展欧几里得算法可以算ax+by=gcd(a,b)的通解,不过一般没有这个需求,而是用于求某些特殊的解,例如求解逆元,逆元是除法求模操作常用的工具

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kunyuwan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值