扩展gcd

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

先复习求gcd的内容

原理:两个整数的最大公约数等于较小的那个数两数相除余数最大公约数
在这里插入图片描述

即gcd(a,b) = gcd(b,a%b)

再看扩展gcd

先了解裴蜀(贝祖)定理

裴蜀(贝祖)定理:若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x、y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。
同时可知对于一般方程ax+by=c有解的条件为c%gcd(a,b)=0。

拓展gcd即是要求ax+by=gcd(a,b)中x、y的整数解

设有ax+by=gcd(a,b),显然,当b = 0时,gcd(a,b) = a,x = 1,y = 任何数。为了方便这里使 y = 0。
当 b != 0时
假设

a * x1+b * y1 = gcd(a,b)
b * x2+(a % b) * y2 = gcd(b,a % b) 且gcd(a,b) = gcd(b,a%b)
根据取余的本质a % b = a - a / b * b进行推导

在这里插入图片描述
得到公式:在这里插入图片描述

以47和30为例:
在这里插入图片描述

可以从下往上从x = 1,y = 0开始用刚刚得到的公式在这里插入图片描述依次向上推导x 和 y。

推导过程转换为代码:

typedef long long ll;
void ex_gcd(ll a,ll b,ll &x1,ll &y1)
{
    if(b==0){
        x1=1;
        y1=0;
    }else{
        ll x2,y2;
        ex_gcd(b,a%b,x2,y2);
        x1=y2;
        y1=(x2-(a/b)*y2);
    }
}
于是就得到了求ax+by=gcd(a,b)一组解的方法

稍改代码还可以求出gcd(a,b)

typedef long long ll;
ll ex_gcd(ll a,ll b,ll &x1,ll &y1)
{
    if(b==0){
        x1=1;
        y1=0;
        return a;
    }else{
    	ll g;
        ll x2,y2;
        ll gcd = ex_gcd(b,a%b,x2,y2);
        x1=y2;
        y1=(x2-(a/b)*y2);
        return gcd;
    }
}

得到一组解后再求通解
已知a * x0 + b * y0 = gcd(a,b);
设 a1 = a / gcd(a,b)
b1 = b / gcd(a,b)

a1 * x0 + b1 * y0 = 1;
把式子加n * a1 * b1再减去n * a1 * b1变换得
a1 * (x0 + n * b1) + b1 * (y0 - n * a1) = 1;(n为整数)

得到通解为 x = x0 + n * b1

求最小正整数解:

 if(x <= 0)
   x = x % b1 + b1;
   else
   x = x % b1;
再求一般方程ax+by=c的整数解

首先要判断是否有解,有解的条件为c % gcd(a,b)=0
因为 a * x0+b * y0=gcd(a,b)
所以 x = x0 * (c / gcd(a,b)) y = y0 * (c / gcd(a,b))

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值