扩展欧几里得算法


  • 裴蜀定理:对于任意正整数 $a、b$ ,一定存在非零整数 $x、y$ ,使得 $ax + by = (a, b)$ (最大公约数)

image-20230407214744323

1.AcWing877.扩展欧几里得算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<iostream>
using namespace std;

// (a, b) = (b, a mod b)
// return b ? gcd(b, a % b) : a;
int gcd(int a, int b) {
if (!b) return a;
return gcd(b, a % b);
}

// ax + by = (a, b)
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 m;
scanf("%d", &m);
while (m--) {
int a, b, x, y;
scanf("%d%d", &a, &b);
exgcd(a, b, x, y);
printf("%d %d\n", x, y);
}
return 0;
}

2.AcWing878.线性同余方程

  • 给定$a、m、b$,求一个整数 $x$ 使得 $ax≡b(mod~m)$

image-20230407221421828

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<iostream>
using namespace std;

// (a, b) = (b, a mod b)
// return b ? gcd(b, a % b) : a;
int gcd(int a, int b) {
if (!b) return a;
return gcd(b, a % b);
}

// ax + by = (a, b)
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 m;
scanf("%d", &m);
while (m--) {
int a, b, m;
scanf("%d%d%d", &a, &b, &m);
int x, y;
int d = exgcd(a, m, x, y);
if (b % d) puts("impossible");
else printf("%d\n", (long long)x * (b / d) % m);
}
return 0;
}