https://en.wikipedia.org/wiki/Bézout's_identity
https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
和最大的公共约数,称为最大公约数。
在小学数学,我们一般用短除法来求最大公约是。
在计算机中一个一个试除是非常慢的,往往用扩展欧几里得实现。
已知求的一组解。
显然如果将增加,减少,可以得到一组新的解,目标是找到最小的一组解。
int exgcd(int x, int y, int &a, int &b) { if (y == 0) { return a = 1, b = 0, x; } else { int g = exgcd(y, x % y, b, a); b -= x / y * a; return g; } }
当时,。
注意到
因此
a = 2, b = 0
find x, y
ax + by = 2
1 * 2 + 0 * 0 = 2
1 * 2 + 0 * (4 - 2 * 2) = 2
1 * 2 + 0 * 4 = 2
1 * (6 - 1 * 4) + 0 * 4 = 2
1 * 6 + (-1) * 4 == 2
1 * 6 + (-1) * (10 - 1 * 6) = 2
2 * 6 + (-1) * 10 = 2
2 * (46 - 4 * 10) + (-1) * 10 = 2
2 * 46 - 9 * 10 = 2
2 * 46 - 9 * (240 - 5 * 46) == 2
47 * 46 - 9 * 240 = 2
只要互质就可以求乘法逆元
已知和。
希望把他们合并成一个模的方程,或者说明无解,可以用扩展欧几里得。
设。
解出的一组解
新方程为
。
https://www.luogu.com.cn/problem/P1082
求关于的同余方程 的最小正整数解。
一行,包含两个正整数 ,用一个空格隔开。
一个正整数 ,即最小正整数解。输入数据保证一定有解。
3 10
7
【数据范围】
对于 40%的数据,;
对于 60%的数据,;
对于 100%的数据,。
NOIP 2012 提高组 第二天 第一题
#include <bits/stdc++.h> using namespace std; void exgcd(int a, int b, int &x, int &y) { if (b == 0) { x = 1; y = 0; return; } else { exgcd(b, a % b, y, x); y -= a / b * x; } } int main() { int a, b, x, y; cin >> a >> b; exgcd(a, b, x, y); if (x < 0) { x += b; y -= a; } cout << x << endl; }
乘法逆元
直接扩展欧几里得
模合数
https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
扩展欧几里得
a * x + b * y = gcd(a, b)
|x| + |y| 越小越好
输入 a 和 b,保证 a 和 b 互质
求a x % b == 1
a x + b y == 1
需要注意最终求出的 x 可能是负数
https://www.luogu.com.cn/problem/P2613
给出一个有理数 ,求 的值。
这个值被定义为 的解。
一共两行。
第一行,一个整数 。
第二行,一个整数 。
一个整数,代表求余后的结果。如果无解,输出 Angry!
。
233
666
18595654
对于所有数据,保证 ,,且 不同时是 的倍数。
#include <bits/stdc++.h> using namespace std; char s[10020]; int a[10020]; int p = 19260817; int read() { // 读入一个数字mod p的结果 scanf("%s", s); int n = strlen(s); for (int i = 0; i < n; i++) { a[i] = s[n - i - 1] - '0'; } int u = 0; for (int i = n - 1; i >= 0; i--) { u = u * 10 + a[i]; u %= p; } return u; } long long pw(long long x, long long y, long long p) { long long re = 1; for (; y; y >>= 1) { if (y & 1) { re = re * x % p; } x = x * x % p; } return re; } int main() { int A = read(); int B = read(); if (B == 0) { printf("Angry!"); } else { cout << (A * pw(B, p - 2, p) % p) << endl; } }
直接扩展欧几里得
https://codeforces.com/problemset/problem/1244/C
https://www.luogu.com.cn/problem/CF1244C