数论 _ 扩展欧几里得算法

裴蜀定理
对于任意正整数a,b, 一定存在整数x, y,使得 \(ax + by = (a, b)\)

因为\((a,b)\)为常数,令\(d= (a, b)\)
\(ax + by = d\)

扩展欧几里得算法就是用于求上面的x和y。
注意:
x和y不唯一。

证明

因为

\[gcd(a, b) = gcd(b, a\%b) \]

\[bx' + (a \% b)y' = gcd(b, a\%b) \]

\[bx' + (a-\lfloor a/b \rfloor*b)y' = gcd(b, a\%b) \]

\[ay' + b(x'- \lfloor {a / b} \rfloor*y') = gcd(b, a\%b) = gcd (a, b) \]

故而

\[x = y', \quad y = x' - \lfloor {a/b} \rfloor*y' \]

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

代码:

#include <iostream>
#include <algorithm>

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;
    scanf("%d", &n);

    while (n -- )
    {
        int a, b;
        scanf("%d%d", &a, &b);
        int x, y;
        exgcd(a, b, x, y);
        printf("%d %d\n", x, y);
    }

    return 0;
}

应用

线性同余方程

\(a*x ≡ b (\mod m)\)
等价于 \(a*x-m* y' = b\)(x,y'是未知数)

\(y = y'\),则有 \(a*x+m* y = b\)
根据 裴蜀定理,上述等式有解当且仅当 b是gcd(a,m)的倍数。
所以可以用拓展欧几里得算法

代码:

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;


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;
    scanf("%d", &n);
    while (n -- )
    {
        int a, b, m;
        scanf("%d%d%d", &a, &b, &m);

        int x, y;
        int d = exgcd(a, m, x, y);
        if (b % d) puts("impossible");
        else printf("%d\n", (LL)b / d * x % m);
    }

    return 0;
}

求逆元

posted @ 2022-08-26 15:40  kingwzun  阅读(54)  评论(0编辑  收藏  举报