AcWing 877. 扩展欧几里得算法

\(AcWing\) \(877\). 扩展欧几里得算法

一、题目描述

给定 \(n\) 对正整数 \(a_i,b_i\),对于每对数,求出一组 \(x_i,y_i\),使其满足 \(a_i×x_i+b_i×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≤n≤10^5\)
\(1≤a_i,b_i≤2×10^9\)

输入样例

2
4 6
8 18

输出样例

-1 1
-2 1

样例理解:

  • \(2x+3y=1\) 一组可行解:\((-1,1)\)
  • \(8x+18y=2\) 一组可行解:\((-2,1)\)

二、裴蜀定理

裴蜀定理

\(a\),\(b\)是整数,且\(gcd(a,b)=d\),那么:

  • 对于任意的整数\(x\),\(y\),\(ax+by\)都一定是\(d\)的倍数

  • 一定存在整数\(x\),\(y\),使\(ax+by=d\)成立

裴蜀定理推论

\(a,b\)互质 $\Leftrightarrow $ \(gcd(a,b)=1\) $\Leftrightarrow $ 存在整数\(x\),\(y\),使得\(ax+by=1\)

举栗子

\(2x+y=3\)

那么\(a=2\),\(b=1\),\(m=3\),\(gcd(2,1)=1\),\(3\)\(1\)的倍数,所以这个方程一定有整数解。

\(x=1\),\(y=1\)就是一个整数解,还可以有\(x=-2\),\(y=7\)也是一组整数解。

注意:如果一个二元一次方程有正整数解,那么不只是一组解

再举栗子

\(4x+2y=5\)
有没有整数解呢?没有,因为\(a=4,b=2,m=5,gcd(4,2)=2,5\)是除不开\(2\)的,所以没有整数解!

如何求贝祖数?

什么是贝祖数?

比如:\(2x+y=3\),那么符合这个等式的\(x=1\),\(y=1\)就是一组 贝祖数

可以使用 扩展欧几里得算法求贝祖数

举个栗子
\(104x+40y=8\) ,有没有合适的\(x,y\),也就是求贝祖数

通过贝祖定理看一下,它是不是有解: \(gcd(104,40)=8\),\(8\)\(8\)的倍数,所以此方程一定有解,那么解是什么呢?

QQ截图20210301141004.png

扩展欧几里得算法的推导过程:

\(exgcd\)中,我们实际是求不定方程\(ax+by=gcd(a,b)\),并且,我们所返回的值,是这组解\((x,y)\)的最大公因数\(gcd(x,y)\)

所以我们最后得到的解,要通过\(X=x∗k/gcd(a,b),Y=(k−a∗x)/gcd(a,b)\)来进行一个小小的转换,得到一组解

算法实现过程证明

(\(1\))、当 \(b=0\)

\(\large ax+by=gcd(a,0)\),也就是:\(\large ax=gcd(a,0)=a\),所以\(\large x=1\)

那么\(y\)呢?因为普遍意义上的求贝祖数,一般是指不小于零的一组解,那么不小于\(0\)的第一个可能\(y\)值就是:\(y=0\),所以,可以将\(x=1,y=0\)做为一组特解返回,也就是返回了一组不小于零的贝祖数

(\(2\))、当 \(b≠0\)

\(\because ax+by=gcd(a,b)\) 【原计算式】

\(gcd(b,a\%b)=gcd(a,b)\) 【辗转相除法】

\(\therefore ax+by=gcd(a,b)=gcd(b,a\%b)=b\cdot x_0+(a\%b)\cdot y_0\) ① 【变量互换,最终是一致滴~】

\(\because a\%b=a-⌊\frac{a}{b}⌋\cdot b\) ②【用整除向下取整来描述扣去\(a\)中所有的\(b\),剩下的就是余数】

将②代入①
\(\therefore ax+by=bx_0+(a-⌊\frac{a}{b}⌋\cdot b)\cdot y_0\)

\(\therefore ax+by=ay_0+b(x_0-⌊\frac{a}{b}⌋\cdot y_0)\)

\(\therefore x=y_0,y=x_0-⌊\frac{a}{b}⌋y_0\)

三、实现代码

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

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

int main() {
    int n;
    cin >> n;
    while (n--) {
        int a, b;
        cin >> a >> b;
        int x, y;
        exgcd(a, b, x, y);
        printf("%d %d\n", x, y);
    }
    return 0;
}

四、三者之间的关系

1. 裴蜀定理

  • 对于任意一对正整数\(a,b\),一定存在非零整数\(x,y\)使得\(ax+by=gcd(a,b)\)

  • 可以用来判断方程\(ax+by=c\)是否有解,只要看\(c\)是否是\(gcd(a,b)\)的倍数

2. 扩展欧几里得算法

如果方程\(ax+by=c\)有解,那么扩欧可以求方程\(ax+by=gcd(a,b)\)一组解(\(x_0,y_0\))

3.线性同余方程

给定\(a,b,m\)构造出\(x\)使得\(ax≡b(mod\ m)\)成立

\(ax≡b(mod\ m)⟺ax=my+b\)(\(y\)是整数)

由此可知\(ax−my=b\)

\(y'=−y\)则有\(ax+my'=b\)

则构造\(x\)一定使得\(ax+my'=b\)有解

根据裴蜀定理可知该方程有解的充要条件是\((a,m)|b\)

\(d=(a,m)\),若\(d∤b\)\(x\)不存在

\(d|b\),则可以用 扩展欧几里得算法 算出\(ax+bm=gcd(a,m)=d\)\(x_0,y_0\)

再将\(x_0×\frac{b}{d},y_0×\frac{b}{d}\)得到\(x\)\(y'\)

posted @ 2021-10-07 10:01  糖豆爸爸  阅读(468)  评论(0编辑  收藏  举报
Live2D