AcWing 203. 同余方程

\(AcWing\) \(203\). 同余方程

一、题目描述

求关于 \(x\) 的同余方程 \(ax≡1~(mod~b)\)最小正整数解

输入格式
输入只有一行,包含两个正整数 \(a,b\),用一个空格隔开。

输出格式
输出只有一行,包含一个正整数 \(x\),表示最小正整数解。

输入数据保证一定有解。

数据范围
\(2≤a,b≤2×10^9\)

输入样例

3 10

输出样例

7

样例解读:\(3*7\%10=1\),此时\(7\)是最小正整数解

二、解题思路

线性同余方程模板题

因为题目说一定有解。根据裴蜀定理,线性同余方程 \(a*x≡b(mod~ m)\)有解,当且仅当\(gcd(a,m)|b\)

回到本题,就是 \(gcd(a,b)=1\),对照通用形式\(\large ax+my=b\),上面的方程对位改写为 \(\large ax+by=1\)

解释:

通用式 $a*x≡b(mod~ m) \Leftrightarrow ax+my=b $

本题式 \(a*x≡1~(m od~b) \Leftrightarrow ax+by=1\)

使用扩欧解题两步走

  • 用扩展欧几里得算法求出方程\(ax+by=1\)的一组解\((x_0,y_0)\)
  • \(x_0~mod~b\),转移到 \(1\sim b\) 区间内即可

注意

  • \(long\) \(long\)
  • \(C ++ \) 中的取模较为特殊,要用 \((x \% b + b) \% b\) 代码进行取模

三、实现代码

#include <cstdio>
using namespace std;
typedef long long LL;
//快读
char buf[1 << 23], *p1 = buf, *p2 = buf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

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 a = read(), b = read();

    int x, y;
    exgcd(a, b, x, y);
    printf("%d\n", ((LL)x % b + b) % b);
    return 0;
}
posted @ 2022-05-24 17:06  糖豆爸爸  阅读(58)  评论(0编辑  收藏  举报
Live2D