给出a、b、c,,给出
a
∗
x
+
b
∗
y
=
c
a*x+b*y=c
a∗x+b∗y=c中,x、y满足一定条件的解。
这时我们就要用到扩展都几里德了。
首先要知道一个性质:若
a
∗
x
+
b
∗
y
=
c
a*x+b*y=c
a∗x+b∗y=c有解,则有
c
=
k
∗
g
c
d
(
a
,
b
)
,
k
∈
Z
c=k*gcd(a,b),k∈Z
c=k∗gcd(a,b),k∈Z,这一点可以利用唯一分解定理证得。
利用上面的性质,我们将等式两边同除于
k
k
k得到:
a
∗
x
a*x
a∗x1
+
b
∗
y
+b*y
+b∗y1
=
g
c
d
(
a
,
b
)
=gcd(a,b)
=gcd(a,b)
(
1
)
(1)
(1)
用欧几里得得到:
b
∗
x
b*x
b∗x2
+
a
%
b
∗
y
+a\%b*y
+a%b∗y2
=
g
c
d
(
b
,
a
%
b
)
=gcd(b,a\%b)
=gcd(b,a%b)
一直递归重复计算,终点是:
b
∗
x
b*x
b∗xn
+
0
∗
y
+0*y
+0∗yn
=
g
c
d
(
b
,
0
)
=
b
=gcd(b,0)=b
=gcd(b,0)=b
得一组解:
x
n
=
1
x_n=1
xn=1 ,
y
n
=
0
y_n=0
yn=0 (
y
n
y_n
yn可以回溯到前两组解证明确实是0)
接下来我们要利用回溯:
我们知道 :
a
%
b
=
a
−
[
a
/
b
]
∗
b
a\%b=a-[a/b]*b
a%b=a−[a/b]∗b
得到:
b
∗
x
b*x
b∗x2
+
{
a
−
[
a
/
b
]
∗
b
}
∗
y
+\{a-[a/b]*b\}*y
+{a−[a/b]∗b}∗y2
=
g
c
d
(
b
,
a
%
b
)
=gcd(b,a\%b)
=gcd(b,a%b)
化简得:
b
∗
{
x
b*\{x
b∗{x2
−
[
a
/
b
]
∗
y
-[a/b]*y
−[a/b]∗y2
}
+
a
∗
y
\}+a*y
}+a∗y2
=
g
c
d
(
b
,
a
%
b
)
=gcd(b,a\%b)
=gcd(b,a%b)
(
2
)
(2)
(2)
联立
(
1
)
(
2
)
(1)(2)
(1)(2)得
x
1
=
y
2
x_1=y_2
x1=y2,
y
1
=
x
2
−
[
a
/
b
]
∗
y
2
y_1=x_2-[a/b]*y_2
y1=x2−[a/b]∗y2
这样我们就可以通过
x
x
xi-1,
y
y
yi-1得到:
x
x
xi,
y
y
yi
回溯到最终时,我们会得到
x
x
x1,
y
y
y1,但是别忘了这是我们通过对等式作了改变得到的,我们还需要将结果在
∗
k
*k
∗k。
另外,我们还有一直通解:
x
x
x通=
x
+
b
/
g
c
d
(
a
,
b
)
x+b/gcd(a,b)
x+b/gcd(a,b) ,
y
y
y通=
y
−
a
/
g
c
d
(
a
,
b
)
y-a/gcd(a,b)
y−a/gcd(a,b)
模板
typedef long long LL;
LL gcd(LL a,LL b){
return b==0 ? a : gcd(b,a%b);
}
LL exGcd(LL &x,LL &y,LL a,LL b){
if(b==0){
x=1,y=0;
return a;
}
LL GCD=exGcd(x,y,b,a%b);
int t=x;
x=y;
y=t-a/b*y;
return GCD;
}
再贴一道题 洛谷1082
题意:求
a
∗
x
−
y
∗
b
=
1
a*x-y*b=1
a∗x−y∗b=1时,
x
x
x的最小正整数解
ac代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL exgcd(LL &x,LL &y,LL a,LL b){
if(b==0){
x=1;y=0;
return a;
}
LL GCD=exgcd(x,y,b,a%b);
LL t=x;
x=y;
y=t-(a/b)*y;
return GCD;
}
int main(){
LL a,x,b,y,c;//a*x+b*y=c;
cin>>a>>b;
c=1;
if(c%__gcd(a,b)==1) cout<<"no"<<endl;
else {
LL GCD=exgcd(x,y,a,b);
int k=c/GCD;
x*=k;
y*=k;
int tx=b/GCD,ty=-a/GCD;
while(x<0) x+=tx,y+=ty;
cout<<x<<endl;
}
return 0;
}