【算法学习笔记】35:扩展欧几里得算法求解线性同余方程

线性同余方程问题

线程同余方程问题是指 a x ≡ b ( m o d m ) ax \equiv b~(mod~m) ax≡b (mod m),给定 a a a、 b b b和 m m m,找到一个整数 x x x使得该方程成立,即使得 a x m o d m = b ax~mod~m=b ax mod m=b,随便返回任何一个解都可以。

例如 4 x ≡ 3 ( m o d 5 ) 4x \equiv 3~(mod~5) 4x≡3 (mod 5),那么 x x x的一个可能的解可以是 2 2 2。

接下来用扩展欧几里得算法尝试构造这个解。从 a x ≡ b ( m o d m ) ax \equiv b~(mod~m) ax≡b (mod m)可知,一定存在一个 y y y使得:
a ⋅ x = m ⋅ y + b a \cdot x = m \cdot y + b a⋅x=m⋅y+b

也就是说,因为 a x ax ax模 m m m的余数是 b b b,所以 a x ax ax一定可以表示成 m m m的整数 y y y倍再加上一个 b b b。也就是:
a x − m y = b ax - my = b ax−my=b

令 y ′ = y y' = y y′=y,那么就是:
a x + m y ′ = b ax + my' = b ax+my′=b

因此原线性同余方程问题求 x x x有解,等价于这个方程求 x x x和 y ′ y' y′有解。而根据扩展欧几里得算法里所讨论的, a a a是 g c d ( a , m ) gcd(a,~m) gcd(a, m)的倍数, m m m也是 g c d ( a , m ) gcd(a,~m) gcd(a, m)的倍数,所以它们拼到一起也必须是 g c d ( a , m ) gcd(a,~m) gcd(a, m)的倍数。

因此,这个方程有解的充要条件 是 b b b必须是 g c d ( a , m ) gcd(a,~m) gcd(a, m)的倍数,也即 g c d ( a , m ) ∣ b gcd(a,~m)~|~b gcd(a, m) ∣ b 。

例题:AcWing 878. 线性同余方程

这题最终结果要限制在int范围内,因为 m m m也是在int范围内的,并且:
a x + m y = b ⇔ a ( k m + r ) + m y = b ⇔ a r + m ( a k + y ) = b ax + my =b \\ \Leftrightarrow a(km + r) + my = b \\ \Leftrightarrow ar + m(ak + y) = b ax+my=b⇔a(km+r)+my=b⇔ar+m(ak+y)=b

也就是说,把系数 x x x变成 r = x m o d m r = x~mod~m r=x mod m时,另一个系数只要从 y y y变成 a k + y ak+y ak+y就可以了,其中 k = ⌊ x m ⌋ k = \lfloor \frac{x}{m} \rfloor k=⌊mx⌋。

所以可以直接把结果 x x x模 m m m,一定也是一个合法的解,并且满足在int范围内的要求。

cpp 复制代码
#include <iostream>

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);
    // d = b * y + (a % b) * x = b * y + (a - a / b * b) * x
    //   = a * x + b * (y - a / b * x)
    y -= a / b * x;
    return d;
}

int main() {
    int t; cin >> t;
    
    while (t -- ) {
        int a, b, m; cin >> a >> b >> m;
        // ax % m = b, ax + my' = b, iff gcd(a, m) = d | b
        int x, y;
        int d = exgcd(a, m, x, y);
        if (b % d) puts("impossible");
        else cout << (LL)x * (b / d) % m << endl;
    }
    
    return 0;
}
相关推荐
稚南城才子,乌衣巷风流24 分钟前
支配树(Dominator Tree)详解:概念、算法与应用
算法
稚南城才子,乌衣巷风流1 小时前
动态开点:原理、实现与应用场景
数据结构·算法
yyds_yyd_100861 小时前
1464. 数组中两元素的最大乘积(2026.07.27)
数据结构·c++·算法·leetcode
KaMeidebaby2 小时前
卡梅德生物技术快报 | 核酸适配体文库测序:核酸适配体文库测序的技术原理、实验流程与数据解析
前端·网络·数据库·人工智能·算法
geovindu3 小时前
CSharp: Breadth First Search Algorithm and Depth First Search Algorithm
开发语言·后端·算法·c#·.net·搜索算法
ekkoalex4 小时前
训练框架以及算法实现的框架
算法
DFT计算杂谈4 小时前
交错磁研究进展材料物性与交叉应用
数据库·人工智能·python·opencv·算法
玖玥拾4 小时前
LeetCode 26 删除有序数组中的重复项
算法·leetcode
Kina_C5 小时前
LVS负载均衡的十二种核心调度算法
linux·运维·算法·负载均衡·lvs
吞下星星的少年·-·5 小时前
牛客技能树:小红走矩阵(dp入门)
算法·dp