exgcd&二元一次丢番图方程

exgcd,二元一次丢番图方程

1.定理

对于任意整数\(a,b\),存在一对整数\(x,y\),满足\(ax + by = gcd(a,b)\).

2.证明

1
2
3
4
5
int gcd(int a,int b) {
if (b == 0)
return a;
return gcd(b,a % b);
}

这是辗转相除法求gcd的代码。

我们可以发现当\(b = 0\)时,有一组\(x = 1,y = 0\),使得\(ax + by = a \times 1 + b \times 0 = gcd(a,b) = a\)

对于任意一组\(a,b\),假设存在一对整数\(x,y\)使得\(bx + (a \% b)y = gcd(b,a \% b) = gcd(a,b)\),对它变形: \[ bx + (a \% b)y = gcd(b,a \% b) = gcd(a,b)\\bx + (a - b \times \lfloor a / b \rfloor)y = gcd(a,b)\\ya + (x - y \times \lfloor a / b \rfloor)b = gcd(a,b) \] 所以我们有了一对\(x' = y,y' = x - y * \lfloor a / b \rfloor\)使得\(ax' + by' = gcd(a,b)\)

3.代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<cstdio>

using namespace std;

int a,b,x,y,gcd;

int exgcd(int a,int b,int &x,int &y) {
if (b == 0) {
x = 1,y = 0;
return a;
}
int d = exgcd(b,a % b,x,y);
int z = x;
x = y,y = z - (a / b) * y;
}

int main() {
scanf("%d%d",&a,&b);
gcd = exgcd(a,b,x,y);
printf("%d %d\n",x,y);
return 0;
}

4.求通解

上文中我们求出了一对\(x_0,y_0\)满足\(ax_0 + by_0 = gcd(a,b)\),现在来求通解。

取一组解\((x_1,y_1)\),再任取一组解\((x_2,y_2)\),有: \[ ax_1 + by_1 = ax_2 + by_2 = gcd(a,b)\\a(x_1 - x_2) = b(y_2 - y_1)\\两边同时除以gcd(a,b),设a / gcd(a,b) = a',b / gcd (a,b) = b'\\a'(x_1 - x_2) = b'(y_2 - y_1)\\此时gcd(a',b') = 1\\所以x_1 - x_2 = kb',y_2 - y_1 = ka' \]

5.另外一个定理

关于整数\(x,y\)的方程\(ax + by = c\)有解的充要条件是\(gcd(a,b)|c\)