知识储备
扩展欧几里得定理
欧几里得定理
(未掌握的话请移步扩展欧几里得)
正题
设存在
ax+by=gcd(a,b)
a
x
+
b
y
=
g
c
d
(
a
,
b
)
,求x,y。
我们已经知道了用扩欧求解的方法是递归,终止条件是x==1,y==0;
int exgcd( int a, int b, int &x, int &y ) {
if( b == 0 ) {
x = 1;
y = 0;
return a;
}
int tmp = a % b;
if( tmp > b ) swap( tmp, b );
int ans=exgcd(b,a%b,x,y);
tmp = x;
x = y;
y = tmp - a / b * y;
return ans;
}
到b==0时,我们可以得到一组解:(1,0)。
接下来再逐步回带,求出所有可能的解。具体是为什么呢?
证明
已知:
- ax1+by1=gcd(a,b) a x 1 + b y 1 = g c d ( a , b )
- bx2+(amodb)y2=gcd(a,b) b x 2 + ( a m o d b ) y 2 = g c d ( a , b )
- amodb=a−a/b∗b a m o d b = a − a / b ∗ b
可求得:
ax1+by1=bx2+(amodb)y2=gcd(a,b)
a
x
1
+
b
y
1
=
b
x
2
+
(
a
m
o
d
b
)
y
2
=
g
c
d
(
a
,
b
)
即
ax1+by1=bx2+(a−a/b∗b)y2=gcd(a,b)
a
x
1
+
b
y
1
=
b
x
2
+
(
a
−
a
/
b
∗
b
)
y
2
=
g
c
d
(
a
,
b
)
化简得
ax1+by1=bx2+ay2−a/b∗b∗y2=gcd(a,b)
a
x
1
+
b
y
1
=
b
x
2
+
a
y
2
−
a
/
b
∗
b
∗
y
2
=
g
c
d
(
a
,
b
)
所以可证出:
对于每一次递归中的x1y1,与上一次递归中的x2y2存在如下关系:
x1=y2
x
1
=
y
2
,
y1=x2−a/b∗y2
y
1
=
x
2
−
a
/
b
∗
y
2
证明毕,
每次的x和y均存在递归关系,所以我们可以在求得一组解后回溯时回带求出其他解,此时计数即可。
P.S.
对于求方程正整数解的个数的题,需要注意特判
设ax+by=c,给定a,b,c,求x,y的正整数解个数
- x=0,y=0,z=0时,方程无数解
- x=0,y=0,z!=0时,方程无解
- x,y<0,z>0时方程无解,反之亦然