这个算法是用来解决这样的问题的:
给定
a,b,c
a
,
b
,
c
,求
ax+by=c
a
x
+
b
y
=
c
这个不定方程的最小非负整数解。
扩欧求的实际上是
ax+by=gcd(a,b)
a
x
+
b
y
=
g
c
d
(
a
,
b
)
这个方程的解,所以只有当 gcd(a,b)|c g c d ( a , b ) | c 的时候才有整数解。
那么怎么求呢?
当 b=0 b = 0 时
gcd(a,b)=a,x=1,y=0
g
c
d
(
a
,
b
)
=
a
,
x
=
1
,
y
=
0
否则,我们设
bx′+(a % b)y′=gcd(b,a % b)
b
x
′
+
(
a
%
b
)
y
′
=
g
c
d
(
b
,
a
%
b
)
因为
gcd(b,a % b)=gcd(a,b)
g
c
d
(
b
,
a
%
b
)
=
g
c
d
(
a
,
b
)
所以
ax+by=bx′+(a % b)y′
a
x
+
b
y
=
b
x
′
+
(
a
%
b
)
y
′
=bx′+(a−⌊ab⌋∗b)y′
=
b
x
′
+
(
a
−
⌊
a
b
⌋
∗
b
)
y
′
=ay′+b(x′−⌊ab⌋∗y′)
=
a
y
′
+
b
(
x
′
−
⌊
a
b
⌋
∗
y
′
)
则
x=y′,y=(x′−⌊ab⌋∗y′)
x
=
y
′
,
y
=
(
x
′
−
⌊
a
b
⌋
∗
y
′
)
这个递归过程正好是求gcd的过程,那么在回溯时把 x,y x , y 更新一下就好了
Code
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int exgcd(int a, int b, int &x, int &y)
{
if (!b) {
x = 1;
y = 0;
return a;
}
int gcd = exgcd(b, a % b, x, y);
int tmp = x;
x = y;
y = tmp - a / b * x;
return gcd;
}
int main(void)
{
int a, b, c, x, y;
cin >> a >> b >> c;
int gcd = exgcd(a, b, x, y);
if (c % gcd) printf("No Solution");
else {
a /= gcd;
b /= gcd;
c /= gcd;
x = ((x % b) + b) % b;
y = (c - a * x) / b;
cout << x << ' ' << y;
}
return 0;
}