扩展欧几里得算法
e x g c d exgcd exgcd一般是用来求解 a x + b y = c ax+by=c ax+by=c这样的方程的。
首先,我们可以证明 a x + b y = gcd ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b)。证明如下:
假设我们已经证得
b
x
′
+
(
a
m
o
d
b
)
y
′
=
gcd
(
b
,
a
m
o
d
b
)
(
a
m
o
d
b
≠
0
)
bx'+(a \ mod \ b)y'=\gcd(b,a \ mod \ b)(a \ mod \ b \neq 0)
bx′+(a mod b)y′=gcd(b,a mod b)(a mod b=0)
a
x
+
b
y
=
gcd
(
a
,
b
)
a
x
+
b
y
=
gcd
(
b
,
a
m
o
d
b
)
a
x
+
b
y
=
b
x
′
+
(
a
m
o
d
b
)
y
′
=
b
x
′
+
(
a
−
⌊
a
b
⌋
×
b
)
y
′
=
b
x
′
+
a
y
′
−
⌊
a
b
⌋
×
b
y
′
=
a
y
′
+
b
(
x
′
−
⌊
a
b
⌋
y
′
)
\begin{aligned} ax+by&=\gcd(a,b) \\ ax+by&=\gcd(b,a \ mod \ b) \\ ax+by&=bx'+(a \ mod \ b)y' \\ &=bx'+(a-\lfloor\frac{a}{b}\rfloor\times b)y' \\ &=bx'+ay'-\lfloor\frac{a}{b}\rfloor\times by' \\ &=ay'+b(x'-\lfloor\frac{a}{b}\rfloor y') \end{aligned}
ax+byax+byax+by=gcd(a,b)=gcd(b,a mod b)=bx′+(a mod b)y′=bx′+(a−⌊ba⌋×b)y′=bx′+ay′−⌊ba⌋×by′=ay′+b(x′−⌊ba⌋y′)
得 a x + b y = a y ′ + b ( x ′ − ⌊ a b ⌋ y ′ ) ax+by=ay'+b(x'-\lfloor\frac{a}{b}\rfloor y') ax+by=ay′+b(x′−⌊ba⌋y′)
{ x = y ′ y = x ′ − ⌊ a b ⌋ y ′ \left\{\begin{matrix}x=y'\\y=x'-\lfloor\frac{a}{b}\rfloor y'\end{matrix}\right. {x=y′y=x′−⌊ba⌋y′
当 a m o d b = 0 a \ mod \ b=0 a mod b=0时, a x + b y = gcd ( a , b ) = b ax+by=\gcd(a,b)=b ax+by=gcd(a,b)=b,所以此时 x = 0 , y = 1 x=0,y=1 x=0,y=1
所以 a x + b y = gcd ( a , b ) ax+by=\gcd(a,b) ax+by=gcd(a,b)是有解的,那么当 g c d ( a , b ) ∣ c gcd(a,b)|c gcd(a,b)∣c时, a x + b y = c ax+by=c ax+by=c也是有解的,递归求解即可。
code
void exgcd(int a,int b){
if(b==0){
x=1;y=0;d=a;
return;
}
exgcd(b,a%b);
int t=x;x=y;y=t-a/b*y;
}
例题
#include<bits/stdc++.h>
using namespace std;
int t;
long long x,y,d;
void exgcd(int a,int b){
if(b==0){
x=1;y=0;d=a;
return;
}
exgcd(b,a%b);
long long t=x;x=y;y=t-a/b*y;
}
int main()
{
long long a,b,c,vk,v1,v2,v3,v4;
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld",&a,&b,&c);
exgcd(a,b);
if(c%d>0){
printf("-1\n");
continue;
}
x=x*c/d;y=y*c/d;
a/=d;b/=d;
if(y<0){
vk=-y/a;
x-=vk*b;y+=vk*a;
}
while(y<=0){
x-=b;y+=a;
}
if(x<0){
vk=-x/b;
x+=vk*b;y-=vk*a;
}
while(x<=0){
x+=b;y-=a;
}
if(x>0&&y>0){
vk=x/b;
x-=vk*b;y+=vk*a;
if(x==0){
x+=b;y-=a;
}
v1=x;v4=y;
vk=y/a;
x+=vk*b;y-=vk*a;
if(y==0){
x-=b;y+=a;
}
v3=x;v2=y;
printf("%lld %lld %lld %lld %lld\n",(v3-v1)/b+1,v1,v2,v3,v4);
}
else{
v1=x;
vk=-y/a;
y+=vk*a;x-=vk*b;
while(y<=0){
x-=b;y+=a;
}
v2=y;
printf("%lld %lld\n",v1,v2);
}
}
return 0;
}