介绍扩展欧几里得算法之前,我们先介绍贝祖定理,即对任意整数 a , b a,b a,b,那么一定存在整数 x , y x,y x,y,使得 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)。
使用欧几里得算法(辗转相除法)我们可知:当到达递归边界时有 b = 0 , a = g c d ( a , b ) b=0,a=gcd(a,b) b=0,a=gcd(a,b),我们可以得到一个式子 a ⋅ 1 + b ⋅ 0 = g c d ( a , b ) , x = 1 , y = 0 a·1+b·0=gcd(a,b),x=1,y=0 a⋅1+b⋅0=gcd(a,b),x=1,y=0,注意这时的 a a a和 b b b与最开始的 a a a和 b b b不一样, 所以我们要想求解出最开始的 x x x和 y y y,就要回到最开始的样式,因为我们这个过程是使用递归算法得到的,所以我们这需要逆向递推,就可以算出最开始的 x x x和 y y y。
上下两层
x
x
x和
y
y
y的关系如下:
因为
a
x
+
b
y
=
g
c
d
(
a
,
b
)
ax+by=gcd(a,b)
ax+by=gcd(a,b),
b
x
+
(
a
%
b
)
y
=
g
c
d
(
b
,
a
%
b
)
bx+(a\%b)y=gcd(b,a\%b)
bx+(a%b)y=gcd(b,a%b);
又因为
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
gcd(a,b)=gcd(b,a\%b)
gcd(a,b)=gcd(b,a%b);
所以
a
x
0
+
b
y
0
=
b
x
+
(
a
%
b
)
y
=
b
x
+
[
a
−
(
a
/
b
)
b
]
y
ax_{0}+by_{0}=bx+(a\%b)y=bx+[a-(a/b)b]y
ax0+by0=bx+(a%b)y=bx+[a−(a/b)b]y;
即
a
x
0
+
b
y
0
=
a
y
+
b
[
x
−
(
a
/
b
)
y
]
ax_{0}+by_{0}=ay+b[x-(a/b)y]
ax0+by0=ay+b[x−(a/b)y];
所以
x
0
=
y
y
0
=
x
−
(
a
/
b
)
y
x_{0}=y\qquad y_{0}=x-(a/b)y
x0=yy0=x−(a/b)y ;
typedef long long ll;
ll x, y;
void exgcd(ll a, ll b){//扩展欧几里得算法
if(b == 0){
x = 1;
y = 0;
return;
}
exgcd(b,a%b);
ll temp = x;//向上推求解最开始的x,y
x = y;
y = temp - (a/b) * y;
}
求解任意方程 a x + b y = n ax+by=n ax+by=n的一个整数解
在上面我们证明 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)一定有整数解,进一步利用它来求解任意方程 a x + b y = n ax+by=n ax+by=n,证明如下:
- 判断方程 a x + b y = n ax+by=n ax+by=n是否有整数解,有解的条件是 g c d ( a , b ) ∣ n gcd(a,b)|n gcd(a,b)∣n(即 g c d ( a , b ) gcd(a,b) gcd(a,b)可以整除n);
- 用扩展欧几里得算法求 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的一个解 ( x 0 , y 0 ) (x_{0},y_{0}) (x0,y0);
- 在 a x 0 + b y 0 = g c d ( a , b ) ax_{0}+by_{0}=gcd(a,b) ax0+by0=gcd(a,b)的两边同时乘以 n g c d ( a , b ) \frac{n}{gcd(a,b)} gcd(a,b)n,即 a x 0 n g c d ( a , b ) + b y 0 n g c d ( a , b ) = n ax_{0}\frac{n}{gcd(a,b)}+by_{0}\frac{n}{gcd(a,b)}=n ax0gcd(a,b)n+by0gcd(a,b)n=n;
- 对照 a x + b y = n ax+by=n ax+by=n,可得它的一个整数解 ( x 1 , y 1 ) (x_{1},y_{1}) (x1,y1), x 1 = x 0 n g c d ( a , b ) y 1 = y 0 n g c d ( a , b ) x_{1}=x_{0}\frac{n}{gcd(a,b)}\qquad y_{1}=y_{0}\frac{n}{gcd(a,b)} x1=x0gcd(a,b)ny1=y0gcd(a,b)n;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll x, y;
ll exgcd(ll a, ll b){
if(b == 0){
x = 1;
y = 0;
return a;
}
ll ans = exgcd(b,a%b);
ll temp = x;
x = y;
y = temp - (a/b) * y;
return ans;
}
int main(){
ll a, b, n;
cin >> a >> b >> n;
ll ans = exgcd(a,b);
if(n % ans == 0) cout << n/ans*x << " " << n/ans*y << endl;
//cout << (x*n/ans%(b/ans)+b/ans)%(b/ans) << endl; x的非负数处理
return 0;
}