扩展欧几里得——解ax+by = c、ax≡c(mod m)

解ax+by = gcd(a, b)

扩展欧几里得算法可以用来解这样一个方程: a x + b y = g c d ( a , b ) ax+by = gcd(a, b) ax+by=gcd(a,b),其中a,b是起初给定的数值(根据数论中的相关定理可以证明肯定有整数解 ,我也信了)

欧几里得算法中(辗转相除法),它总是把求解gcd(a,b)转化为gcd(b,a%d),当b=0时返回a,此时的a就是gcd,因为达到递归边界时,有a* 1+b* 0=gcd成立,此时也有x=1,y=0

int gcd(int a,int b)
{
    if(b==0)return a;
    else return gcd(b,a%b);
}

求: a x + b y = g c d ( a , b ) ax+by = gcd(a, b) ax+by=gcd(a,b)的一组整数解(x,y),观察:
ax+by = gcd(a, b) ⟹ \Longrightarrow 两个未知数x,y

根据欧几里得算法里面a,b的变化规律,可以再写出一个辅助式子:
bx2+a%by2 = gcd(b,a%b) ⟹ \Longrightarrow +两个未知数x2,y2

由欧几里得算法可知,若b ≠ \neq = 0:gcd(a,b)=gcd(b,a%b)
所以:ax+by = bx2+a%by2
即:ax+by = bx2+(a–(a/b)*b)y2
即:ax+by = ay2+ b*(x2–a/b*y2)
所以:x = y2,y = x2–(a / b) y2

如果一直这样下去,递归到边界:b=0时,返回x=1,y=0,回溯的过程我们就可以求出最初的x,y的值。

ax+by = gcd通解:
在这里插入图片描述
a*b/gcd是a和b的最小公倍数

模板:

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

解ax+by = c

ax+by = c存在解的充要条件是c%gcd==0,ax+by = c的通解和ax+by = gcd一样,唯一不同是初始解(x,y)不同:
在这里插入图片描述

方程最小非负整数解的处理

Question1:如果需要求该方程的最小非负整数解,该如何调整?
1、ax+by = gcd(a, b)
容易发现 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)等价于 a ( x − k ⋅ b ) + b ( y + k ⋅ a ) = g c d ( a , b ) a(x−k\cdot b)+b(y+k\cdot a)=gcd(a,b) a(xkb)+b(y+ka)=gcd(a,b)

所以对于x的调整为x=(x%b+b)%b(x的每一个整数解以b为周期)

对于y的调整为y=(y%a+a)%a
2、ax+by = c
同上,因为 a x + b y = c ax+by=c ax+by=c等价于 a ( x − k ⋅ b g c d ) + b ( y + k ⋅ a g c d ) = c a(x−k\cdot \frac{b}{gcd})+b(y+k\cdot \frac{a}{gcd})=c a(xkgcdb)+b(y+kgcda)=c

所以对于x的调整为 x = ( x % ( b g c d ) + b g c d ) % b g c d x=(x\%(\frac{b}{gcd})+\frac{b}{gcd})\%\frac{b}{gcd} x=(x%(gcdb)+gcdb)%gcdb

对于y的调整为 y = ( y % a g c d + a g c d ) % a g c d y=(y\%\frac{a}{gcd}+\frac{a}{gcd})\%\frac{a}{gcd} y=(y%gcda+gcda)%gcda

同余式ax≡c(mod m)的求解

同余式:对于整数a、b、m来说,如果m整除a-b(即(a-b)%m==0),那么就说a与b模m同余,对应同余式为a≡b(mod m),m为同余式的模。例如10与13模3同余,记为10=13(mod 3)。

此处要解决的就是同余式ax≡c(mod m)的求解。根据同余式的定义,有
(ax-c)%m=0成立,因此存在整数-y使得ax-c=-my,即得ax+my=c。

由扩展欧几里得中的结论,当c%gcd(a,m)==0,是方程才有解。

例题:https://www.luogu.org/problem/P1082
代码:

#include<bits/stdc++.h>
using namespace std;
typedef int LL;
const int N=2e6;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    LL gcd=exgcd(b,a%b,x,y);
    //a%b也可以写成a-a/b*b,最开始写成a-b*a/b可能爆精度了,wa了两次
    LL temp=x;
    x=y;
    y=temp-a/b*y;
    return gcd;
}
int main()
{
    LL a,b,x,y;
    while(scanf("%d%d",&a,&b)!=EOF)
    {
        exgcd(a,b,x,y);
        x=(x%b+b)%b;
        printf("%d\n",x);
    }
}
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值