在讲解扩展欧几里得之前我们先回顾下辗转相除法:
gcd(a,b)=gcd(b,a%b)
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
当
a%b==0
a
%
b
==
0
的时候b即为所求最大公约数
好了切入正题:
简单地来说exgcd函数求解的是 ax+by=gcd(a,b) a x + b y = g c d ( a , b ) 的最小正整数解。根据数论的相关知识,一定存在一组解 x,y x , y 使得 ax+by=gcd(a,b) a x + b y = g c d ( a , b ) 当且仅当 a a 与互质的时候。那就来谈谈具体如何来求解吧。
根据辗转相除法的内容 gcd(a,b)=gcd(b,a%b) g c d ( a , b ) = g c d ( b , a % b ) 我们可以得到:
ax1+by1=gcd(a,b)=gcd(b,a%b)=bx2+a%by2⋅⋅⋅⋅⋅⋅①
a
x
1
+
b
y
1
=
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
=
b
x
2
+
a
%
b
y
2
·
·
·
·
·
·
①
又由于 a%b=a−⌊a÷b⌋×b a % b = a − ⌊ a ÷ b ⌋ × b
在计算机中 a%b=⌊a÷b⌋×b=a/b∗b a % b = ⌊ a ÷ b ⌋ × b = a / b ∗ b 所以
bx2+a%by2=bx2+(a−a/b∗b)y2
b
x
2
+
a
%
b
y
2
=
b
x
2
+
(
a
−
a
/
b
∗
b
)
y
2
将等式①变形得:
ax1+b(y1+a/b∗y2)=ay2+bx2
a
x
1
+
b
(
y
1
+
a
/
b
∗
y
2
)
=
a
y
2
+
b
x
2
因为等式左右两边结构相同我们可以解得:
{x1=y2y1=x2−a/b∗y2
{
x
1
=
y
2
y
1
=
x
2
−
a
/
b
∗
y
2
在扩展欧几里得算法的最后一步即 b=0 b = 0 的时候,显然有一对整数 x=1,y=0 x = 1 , y = 0 使得
a∗1+b∗0=gcd(a,0)
a
∗
1
+
b
∗
0
=
g
c
d
(
a
,
0
)
那么我们就可以通过编程实现exgcd了,请仔细体验下代码的精妙之处:
int exgcd(int a,int b,int &x,int &y) {
if(b) {
int d=exgcd(b,a%b,y,x);
y-=a/b*x;
} else {
x=1;
y=0;
return a;
}
}