题目传送门
对于不等式: a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b),给定 a , b a,b a,b,求出符合条件的一组 x , y x,y x,y。
推导: (假定a>=b)
- a x 1 + b y 1 = g c d ( a , b ) ax_1+by_1=gcd(a,b) ax1+by1=gcd(a,b)
- b x 2 + a % b y 2 = g c d ( b , a % b ) bx_2+a\%by_2=gcd(b,a\%b) bx2+a%by2=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 1 + b y 1 = b x 2 + a % b y 2 ax_1+by_1=bx_2+a\%by_2 ax1+by1=bx2+a%by2
- a % b = a − ⌊ a b ⌋ × b a\%b=a-\lfloor\frac{a}{b}\rfloor\times b a%b=a−⌊ba⌋×b
- a x 1 + b y 1 = b x 2 + ( a − ⌊ a b ⌋ × b ) y 2 ax_1+by_1=bx_2+(a-\lfloor\frac{a}{b}\rfloor\times b)y_2 ax1+by1=bx2+(a−⌊ba⌋×b)y2
- a x 1 + b y 1 = a y 2 + b x 2 − ⌊ a b ⌋ × b y 2 ax_1+by_1=ay_2+bx_2-\lfloor\frac{a}{b}\rfloor\times by_2 ax1+by1=ay2+bx2−⌊ba⌋×by2
- a x 1 + b y 1 = a y 2 + b ( x 2 − ⌊ a b ⌋ × y 2 ) ax_1+by_1=ay_2+b(x_2-\lfloor\frac{a}{b}\rfloor\times y_2) ax1+by1=ay2+b(x2−⌊ba⌋×y2)
- x 1 = y 2 , y 1 = x 2 − ⌊ a b ⌋ × y 2 x_1=y_2,y_1=x_2-\lfloor\frac{a}{b}\rfloor\times y_2 x1=y2,y1=x2−⌊ba⌋×y2
向下迭代,直到 b = 0 b=0 b=0,此时将 x = 1 , y = 0 x=1,y=0 x=1,y=0返回,向上迭代,即可得到 x 1 , y 1 x_1,y_1 x1,y1。
通解: 我们刚才求的只是 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的一组特解,但是题目往往让我们求最小整数解。通过求x的最小整数解为例,假设存在另外的一组解 x 0 , y 0 x_0,y_0 x0,y0:
- a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)
- y = g c d ( a , b ) − a x b y=\frac{gcd(a,b)-ax}{b} y=bgcd(a,b)−ax
- y 0 = g c d ( a , b ) − a x 0 b y_0=\frac{gcd(a,b)-ax_0}{b} y0=bgcd(a,b)−ax0
- 假设 x 0 = x + i x_0=x+i x0=x+i
- y 0 = g c d ( a , b ) − a x b − a i b y_0=\frac{gcd(a,b)-ax}{b}-\frac{ai}{b} y0=bgcd(a,b)−ax−bai
- y 0 = y − a i b y_0=y-\frac{ai}{b} y0=y−bai
- 因为 y ∈ Z , y 0 ∈ Z y∈Z,y_0∈Z y∈Z,y0∈Z
- a ∗ i / b ∈ Z a*i/b∈Z a∗i/b∈Z
- 即 a / b ∗ i ∈ Z a/b*i∈Z a/b∗i∈Z
- 若 a , b a,b a,b互质,则 i m i n = b i_{min}=b imin=b
- 若 a , b a,b a,b不互质,那么存在 a ′ / b ′ ∗ i ∈ Z a'/b'*i∈Z a′/b′∗i∈Z
- a ′ = a / g c d ( a , b ) , b ′ = b / g c d ( a , b ) a'=a/gcd(a,b),b'=b/gcd(a,b) a′=a/gcd(a,b),b′=b/gcd(a,b)
由此,可知
x
i
=
x
+
k
∗
i
,
i
=
b
′
=
b
/
g
c
d
(
a
,
b
)
x_i=x+k*i,i=b'=b/gcd(a,b)
xi=x+k∗i,i=b′=b/gcd(a,b)
同理可知,
y
i
=
y
+
k
∗
j
,
j
=
a
′
=
a
/
g
c
d
(
a
,
b
)
y_i=y+k*j,j=a'=a/gcd(a,b)
yi=y+k∗j,j=a′=a/gcd(a,b)
代码(递归版):
void exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x = 1;
y = 0;
return ;
}
exgcd(b,a%b,x,y);
int t = x;
x = y;
y = t - (a / b) * y;
return ;
}
代码(非递归版):
void exgcd(int a,int b,int &x,int &y)
{
x = 1, y = 0;
int x1 = 0, y1 = 1, a1 = a, b1 = b;
while (b1)
{
int q = a1 / b1;
tie(x, x1) = make_tuple(x1, x - q * x1);
tie(y, y1) = make_tuple(y1, y - q * y1);
tie(a1, b1) = make_tuple(b1, a1 - q * b1);
}
return ;
}