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;
}