线性丢番图方程 裴蜀定理 扩展欧几里得算法

二元线性丢番图方程

方程 \(ax+by=c\) 称为二元线性丢番图方程,其中 \(a,b,c\) 为常量,\(x,y\) 为变量,问方程是否有整数解。

该方程实际上是二维平面上的一条直线,无固定解,所以丢番图方程又称为不定方程


在数论中,我们记 \((a,b)\)\(a\)\(b\) 的最大公约数,即 \(gcd(a,b)\) 的简写。

那么,在讨论不定方程是否有整数解上,我们可得到以下定理。


裴蜀定理

如果 \(a,b\in N\) ,则有整数 \(x,y\) 使 \(ax+by=(a,b)\)

这个等式称为裴蜀等式。

推论

  1. 如果 \(a,b\in N\) ,且 \((a,b)=1\) ,当且仅当 \(\exists \ x,y\in N\) ,使 \(ax+by=1\)
  2. 如果 \(a,b\in N\) ,则有则有整数 \(x,y,n\) 使 \(ax+by=(a,b)\times n\)

证明

换个理解方式:对 \(\forall x,y\)\(d=ax+by\)\(d\) 一定是 \((a,b)\) 的整数倍;其中最小的 \(d\) 就是 \((a,b)\)

\(a,b\) 互质, 则 \(d=(a,b)=1\) ,所以 \(ax+by=1\)

那么,如果 \(d\) 不是 \((a,b)\) 的整数倍,不定方程一定没有整数解。


扩展欧几里得算法

问题1

\(ax+by=(a,b)\) 的一组整数解。

算法

\(b= 0\) 时,\(ax+by=a\) ,故而 \(x=1,\ y=0\)

\(b\ne 0\) 时,

由欧几里得算法,\((a,b)=(b,a\%b)\)

由裴蜀定理,

\[\begin{align} (a,b)&=ax+by\\[3mm] (b,a\%b)&=bx_1+(a\ \%\ b)y_1\\[2mm] &=bx_1+(a-\left \lfloor\dfrac{a}{b} \right \rfloor\times b ) y_1\\[1mm] &=ay_1+b(x_1-\dfrac{a}{b}y_1) \end{align} \]

所以 \(x=y_1,\ y=x_1-\frac{a}{b}y_1\\\)

利用递归,先求出下一层的 \(x_1,\ y_1\)

再回代上一层,回代求特解 \(x_0, \ y_0\)

tips

实际上,就是等式两边同时除以 \((a,b)\) ,得到 \(cx+dy=1\)

其中,\(c=\dfrac{a}{(a,b)},\ d=\dfrac{b}{(a,b)}\) ,可以直接写出通解 \(x=x_0+dn,\ y=y_0-cn\)

构造通解

\[\begin{cases} x=x_0+\dfrac{b}{(a,b)}\times k \\[2mm] y=y_0-\dfrac{a}{(a,b)}\times k \end{cases} \]

问题2

\(ax+by=c\) 的一组整数解。

算法

\((a,b)\mid c\) ,则有整数解。

先用扩展欧几里得算法求 \(ax+by=(a,b)\) 的解。

再乘以 \(\dfrac{c}{(a,b)}\) ,即得到原方程的特解 \(x_0,\ y_0\)。(原理就是上面tips的逆运用)

\((a,b)\nmid c\) ,则无整数解。



[AcWing877] 扩展欧几里得算法

题目描述

给定 \(n\) 对正整数 \(a_i, b_i\),对于每对数,求出一组 \(x_i, y_i\),使其满足 \(a_i \times x_i + b_i \times y_i = gcd(a_i, b_i)\)

输入格式

第一行包含整数 \(n\)

接下来 \(n\) 行,每行包含两个整数 \(a_i, b_i\)

输出格式

输出共 \(n\) 行,对于每组 \(a_i, b_i\),求出一组满足条件的 \(x_i, y_i\),每组结果占一行。

本题答案不唯一,输出任意满足条件的 \(x_i, y_i\) 均可。

数据范围

\(1 \le n \le 10^5\),
\(1 \le a_i,b_i \le 2 \times 10^9\)

输入样例:

2
4 6
8 18

输出样例:

-1 1
-2 1

算法

这里就用 \(a=4,\ b=6\) 来手推扩欧算法。

C++ 代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll exgcd(int a,int b,int &x,int &y)
{
    if (b == 0){
        x = 1, y = 0;
        return a;
    }
    int x1, y1, gcd;
    gcd = exgcd(b, a % b, x1, y1);
    x = y1, y = x1 - a / b * y1;
    return gcd;
}

int main()
{
    int n; cin >> n;
    while (n--){
        int a, b, x, y;
        cin >> a >> b;
        int gcd = exgcd(a,b,x,y);
        cout << x << " " << y << endl; 
    }
    return 0;
}
posted @ 2025-02-13 14:47  AKgrid  阅读(153)  评论(0)    收藏  举报