题目传送门

一、理解和感悟

裴蜀定理

裴蜀定理(或贝祖定理)得名于法国数学家艾蒂安·裴蜀,说明了对任何整数\(a\)\(b\)和它们的最大公约数\(d\),关于未知数\(x\)\(y\)的线性不定方程(称为裴蜀等式):若\(a\),\(b\)是整数,且\(gcd(a,b)=d\),那么对于任意的整数\(x\),\(y\),\(ax+by\)都一定是\(d\)的倍数,特别地,一定存在整数\(x\),\(y\),使\(ax+by=d\)成立

推论:\(a\),\(b\)互质的充分必要条件是存在整数\(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\)的倍数,所以此方程一定有解,那么解是什么呢?

AcWing 877. 扩展欧几里得算法

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

我们先来求方程 \(ax+by=gcd(a,b)\)的解

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

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

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

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

\(\because gcd(a,b)=gcd(b,a\%b)\)

并且\(①\ \ \ \ ax+by=gcd(a,b)\)

\(\therefore bx′+(a\%b)y′=gcd(a,b)\)

\(\because a−⌊a/b⌋∗b=a\%b\)

\(\therefore bx′+(a−⌊a/b⌋∗b)y′=gcd(a,b)\)

变形一下:

\(② \ \ \ \ ay′+b(x′−⌊a/b⌋∗y′)=gcd(a,b)\)

对比\(① ②\)系数:

\(\therefore\) \(x=y′,y=x′−⌊a/b⌋∗y′\)

因此可以采取递归算法 先求出下一层的\(x′\)\(y′\) 再利用上述公式回代即可

二、完整代码


#include <bits/stdc++.h>

using namespace std;

/**
 * 功能:扩展欧几里得算法模板
 * @param a 第一个数
 * @param b 第二个数
 * @param x 贝祖数x 最小非负整数
 * @param y 贝祖数y 最小非负整数
 * @return
 */
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() {
    //优化输入
    ios::sync_with_stdio(false);
    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;
}

相关文章:

  • 2021-05-10
  • 2021-09-21
猜你喜欢
  • 2022-02-15
  • 2021-06-01
  • 2021-06-14
相关资源
相似解决方案