爱思创 181253 同余方程 题解

181253 同余方程

题目大意

小B: 求关于 \(x\) 的同余方程 \(a x \equiv 1 \pmod {b}\) 的最小正整数解。
小A: \(a \equiv b \pmod{c}\) 意为 \(a\ mod\ c = b\ mod\ c\)

铺垫知识

扩展欧几里得
根据裴蜀定理可得 \(ax+by=d, g = gcd(a, b), g | d\)
扩展欧几里得就是在求最大公因数的基础上多求了一组满足 \(ax+by=gcd(a, b)\) 的 x 和 y的特解。
小B: 代码是

void ex_gcd(long long a, long long b, long long &x, long long &y)//这道题不用求最大公因数,用void类型。因为要传回两个参数,所以直接用&直接改
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return;//b=0时的特解
    }
    ex_gcd(b, a % b, x, y);//将x、y改为ex_gcd(b, a % b)的解
    int z = x;
    x = y;
    y = z - a / b * y;//更改x和y
    return;
}

思路

这一道题实际上求的是 \(ax+by=1\) 的解,然后输出x的值,但 \(x\) 不一定是最小正整数解。有可能太大,也有可能是负数。
小A: 那么直接用扩展欧几里得得出 \(ax+by=1\) 的解,然后转换成最小正整数解。
小B: 那怎么转换成最小正整数解呢?
小A: 这依然可以解决,\(x\) 批量地减去或加上 \(b\),依然能保证 \(ax+by=1\)

x = (x % b + b) % b;//括号中取模再加,可以处理负数

完整代码

#include<bits/stdc++.h>
using namespace std;
void ex_gcd(long long a, long long b, long long &x, long long &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return;
    }
    ex_gcd(b, a % b, x, y);
    int z = x;
    x = y;
    y = z - a / b * y;
    return;
}
int main()
{
    long long a, b, x, y;
    cin >> a >> b;
    ex_gcd(a, b, x, y);
    cout << (x % b + b) % b;
    return 0;
}
posted @ 2022-12-18 16:43  yuzihang  阅读(55)  评论(0)    收藏  举报