一、最大公约数
一组整数的公约数,是指能够同时整除这组数中每一个数的整数。
一组整数的最大公约数(Greatest Common Divisor,GCD),是指这组数所有公约数中最大的一个。
例如,
6
,
12
,
18
,
30
,
52
6, 12, 18, 30, 52
6,12,18,30,52 的最大公约数是
2
2
2 。
二、欧几里得算法
下面的式子是欧几里得算法的核心:
gcd
(
a
,
b
)
=
gcd
(
b
,
a
m
o
d
b
)
\gcd(a,b) = \gcd(b, a \bmod b)
gcd(a,b)=gcd(b,amodb)
接下来给出证明:
①
a
,
b
a,b
a,b 的公约数必然为
b
,
a
m
o
d
b
b, a \bmod b
b,amodb 的公约数。
设
d
d
d 为
a
,
b
a,b
a,b 的公约数,
a
=
k
b
+
c
a=kb+c
a=kb+c,则
d
∣
a
,
d
∣
b
d \mid a, d \mid b
d∣a,d∣b,则
a
m
o
d
b
=
c
a \bmod b = c
amodb=c,由于
d
∣
a
,
d
∣
(
k
b
)
d \mid a, d \mid (kb)
d∣a,d∣(kb),故
d
∣
c
d \mid c
d∣c ,因此
d
∣
(
a
m
o
d
b
)
d \mid (a \bmod b)
d∣(amodb),又因为
d
∣
b
d \mid b
d∣b,所以
a
,
b
a,b
a,b 的公约数必然为
b
,
a
m
o
d
b
b, a\bmod b
b,amodb 的公约数。
②
b
,
a
m
o
d
b
b, a \bmod b
b,amodb 的公约数必然为
a
,
b
a,b
a,b 的公约数。
设
d
d
d 为
b
,
a
m
o
d
b
b, a\bmod b
b,amodb 的公约数,
a
=
k
b
+
c
a=kb+c
a=kb+c 则
d
∣
b
,
d
∣
(
a
m
o
d
b
)
d \mid b, d\mid (a\bmod b)
d∣b,d∣(amodb) ,则
a
m
o
d
b
=
c
a \bmod b=c
amodb=c,由于
d
∣
(
k
b
)
,
d
∣
c
d \mid (kb), d \mid c
d∣(kb),d∣c,故
d
∣
a
d \mid a
d∣a,又因为
d
∣
b
d \mid b
d∣b,所以
b
,
a
m
o
d
b
b, a\bmod b
b,amodb 的公约数必然为
a
,
b
a, b
a,b 的公约数。
由①②得, a , b a,b a,b 的公约数和 b , a m o d b b, a\bmod b b,amodb 的公约数完全相同,因此,它们的最大公约数也相同,即 gcd ( a , b ) = gcd ( b , a m o d b ) \gcd(a,b)=\gcd(b, a\bmod b) gcd(a,b)=gcd(b,amodb) 。
在计算两个数的最大公约数时,可以根据这个等式,不断递归,直到 b = 0 b=0 b=0 。代码如下。
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
递归过程中 a m o d b a \bmod b amodb 至少将 a a a 的规模减半,所以递归层数为 log n \log n logn 层,复杂度为 O ( log n ) O(\log n) O(logn) 。
三、多个数的最大公约数
计算多个整数的最大公约数时可以根据:
gcd
(
a
1
,
a
2
,
a
3
,
.
.
.
,
a
n
)
=
gcd
(
g
c
d
(
a
1
,
a
2
)
,
a
3
,
a
4
,
.
.
.
,
a
n
)
\gcd(a_1,a_2,a_3,...,a_n)=\gcd(gcd(a_1,a_2), a_3,a_4,...,a_n)
gcd(a1,a2,a3,...,an)=gcd(gcd(a1,a2),a3,a4,...,an)
不断减少数字的个数,最终简化成两个整数的情况。
四、扩展欧几里得算法
扩展欧几里得算法常用于求解类似
a
x
+
b
y
=
g
c
d
(
a
,
b
)
ax+by=gcd(a,b)
ax+by=gcd(a,b) 形式的二元一次方程组的一组可行解。
顾名思义,扩展欧几里得算法与欧几里得算法有相似之处,其实,这两种算法都使用了
gcd
(
a
,
b
)
=
gcd
(
b
,
a
m
o
d
b
)
\gcd(a,b) = \gcd(b, a\bmod b)
gcd(a,b)=gcd(b,amodb) 这条性质不断缩小问题规模,而后回溯求解。因此,不妨构造一个与
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
)
bx+(a\bmod b)y = \gcd(b, a\bmod b)
bx+(amodb)y=gcd(b,amodb) (以下称作方程②) 并且假设已知后面方程组的一组解为
x
=
x
0
,
y
=
y
0
x=x_0, y=y_0
x=x0,y=y0。因此有:
a
x
+
b
y
=
gcd
(
a
,
b
)
=
gcd
(
b
,
a
m
o
d
b
)
=
b
x
0
+
(
a
m
o
d
b
)
y
0
ax+by=\gcd(a,b)=\gcd(b, a\bmod b)=bx_0+(a\bmod b)y_0
ax+by=gcd(a,b)=gcd(b,amodb)=bx0+(amodb)y0
a x + b y = b x 0 + ( a − ⌊ a b ⌋ × b ) y 0 ax+by=bx_0+(a-\lfloor\frac{a}{b}\rfloor\times b)y_0 ax+by=bx0+(a−⌊ba⌋×b)y0
a ( x − y 0 ) + b ( y − x 0 + ⌊ a b ⌋ y 0 ) = 0 a(x-y_0)+b(y-x_0+\lfloor\frac{a}{b}\rfloor y_0)=0 a(x−y0)+b(y−x0+⌊ba⌋y0)=0
故可以得到原方程的解为
x
=
y
0
,
y
=
x
0
−
⌊
a
b
⌋
y
0
x=y_0,y=x_0-\lfloor\frac{a}{b}\rfloor y_0
x=y0,y=x0−⌊ba⌋y0。这样,在得知方程②解的情况下可以推得方程①的解。那么如何求出方程②的解呢?
通过观察两个方程的系数可以发现,从①
→
\rarr
→ ②的过程中,系数会通过取模减小的,那么同欧几里得算法一样,不断递归,使系数减小,直到
b
=
0
b=0
b=0 ,此时根据欧几里得算法有
a
=
gcd
(
a
,
b
)
a=\gcd(a,b)
a=gcd(a,b),求出此时方程
gcd
(
a
,
b
)
x
+
0
y
=
gcd
(
a
,
b
)
\gcd(a,b)x + 0y=\gcd(a,b)
gcd(a,b)x+0y=gcd(a,b) 的解为
x
=
1
,
y
x=1,y
x=1,y 为任意值,不妨设
y
=
0
y=0
y=0,不断回溯得到原方程
a
x
+
b
y
=
gcd
(
a
,
b
)
ax+by=\gcd(a,b)
ax+by=gcd(a,b) 的解。代码如下:
// 其中 d 为最大公约数,可以不写,将 exgcd 函数定义为 void 类型
int exgcd(int a, int b, int &x, int &y){
if (!b){
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, x, y);
int tmp = x;
x = y;
y = tmp - (a / b) * y;
return d;
}
递归过程同欧几里得算法,因此复杂度也为 O ( log n ) O(\log n) O(logn) 。
五、扩展欧几里得算法求出的特解性质
使用扩展欧几里得算法求出的特解
x
=
x
0
,
y
=
y
0
x=x_0, y=y_0
x=x0,y=y0 满足性质
∣
x
0
∣
<
b
,
∣
y
0
∣
<
a
| x_0 | < b, | y_0 | < a
∣x0∣<b,∣y0∣<a 。采用归纳法证明如下:
不妨假设共进行
n
n
n 层递归,原方程为
a
x
+
b
y
=
gcd
(
a
,
b
)
ax+by=\gcd(a,b)
ax+by=gcd(a,b),第
i
i
i 层递归得到的方程为
a
i
x
+
b
i
y
=
gcd
(
a
,
b
)
a_ix+b_iy=\gcd(a,b)
aix+biy=gcd(a,b),该层递归得到的解为
x
=
x
i
,
y
=
y
i
x=x_i, y=y_i
x=xi,y=yi ,递归出口
a
n
x
+
b
n
y
=
gcd
(
a
,
b
)
a_nx+b_ny=\gcd(a,b)
anx+bny=gcd(a,b),其中
b
n
=
0
b_n=0
bn=0。
① 当
gcd
(
a
,
b
)
=
b
i
\gcd(a,b)=b_i
gcd(a,b)=bi 时:
有
a
m
o
d
b
=
0
a \bmod b = 0
amodb=0,因此递归层数
i
=
n
−
1
i=n-1
i=n−1 ,得到解为
x
=
x
n
−
1
=
1
,
y
=
y
n
−
1
=
0
x=x_{n-1}=1, y=y_{n-1}=0
x=xn−1=1,y=yn−1=0,此时满足
∣
x
n
−
1
∣
<
∣
b
n
−
1
∣
,
∣
y
n
−
1
∣
<
∣
a
n
−
1
∣
| x_{n-1} | < |b_{n-1}|, |y_{n-1}| < |a_{n-1}|
∣xn−1∣<∣bn−1∣,∣yn−1∣<∣an−1∣ 。
② 当
gcd
(
a
,
b
)
≠
b
i
\gcd(a,b) \neq b_i
gcd(a,b)=bi 时:
不妨假设第
i
+
1
i+1
i+1 层递归得到的解
x
=
x
i
+
1
,
y
=
y
i
+
1
x=x_{i+1}, y=y_{i+1}
x=xi+1,y=yi+1 满足
∣
x
i
+
1
∣
<
∣
b
i
+
1
∣
,
∣
y
i
+
1
∣
<
∣
a
i
+
1
∣
| x_{i+1} | < | b_{i+1} |, | y_{i+1} | < | a_{i+1} |
∣xi+1∣<∣bi+1∣,∣yi+1∣<∣ai+1∣ 。根据系数递归的公式有
a
i
+
1
=
b
i
,
b
i
+
1
=
a
i
m
o
d
b
i
a_{i+1} = b_i, b_{i+1} = a_i\bmod b_i
ai+1=bi,bi+1=aimodbi 。
则对于
x
i
x_i
xi :
∣
x
i
∣
=
∣
y
i
+
1
∣
<
∣
a
i
+
1
∣
=
∣
b
i
∣
| x_i | = | y_{i+1} | < | a_{i+1} | = | b_i |
∣xi∣=∣yi+1∣<∣ai+1∣=∣bi∣
对于
y
i
y_i
yi :
∣
y
i
∣
=
∣
x
i
+
1
−
⌊
a
i
b
i
⌋
y
i
+
1
∣
⩽
∣
x
i
+
1
∣
+
∣
⌊
a
i
b
i
⌋
y
i
+
1
∣
=
∣
x
i
+
1
∣
+
⌊
a
i
b
i
⌋
∣
y
i
+
1
∣
⩽
∣
b
i
+
1
∣
−
⌊
a
i
b
i
⌋
∣
y
i
+
1
∣
| y_i | = | x_{i+1} - \lfloor \frac{a_i}{b_i} \rfloor y_{i+1} | \leqslant | x_{i+1} | + | \lfloor \frac{a_i}{b_i} \rfloor y_{i+1} | = | x_{i+1} | + \lfloor\frac{a_i}{b_i}\rfloor | y_{i+1} | \leqslant | b_{i+1} | - \lfloor\frac{a_i}{b_i}\rfloor | y_{i+1} |
∣yi∣=∣xi+1−⌊biai⌋yi+1∣⩽∣xi+1∣+∣⌊biai⌋yi+1∣=∣xi+1∣+⌊biai⌋∣yi+1∣⩽∣bi+1∣−⌊biai⌋∣yi+1∣
⩽ a i m o d b i + ⌊ a i b i ⌋ ∣ y i + 1 ∣ ⩽ a i − ⌊ a i b i ⌋ b i + ⌊ a i b i ⌋ ∣ y i + 1 ∣ ⩽ a i − ⌊ a i b i ⌋ ( b i − ∣ y i + 1 ∣ ) \leqslant a_i \bmod b_i + \lfloor\frac{a_i}{b_i}\rfloor | y_{i+1} | \leqslant a_i - \lfloor\frac{a_i}{b_i}\rfloor b_i + \lfloor\frac{a_i}{b_i}\rfloor | y_{i+1} | \leqslant a_i - \lfloor\frac{a_i}{b_i}\rfloor(b_i-|y_{i+1}|) ⩽aimodbi+⌊biai⌋∣yi+1∣⩽ai−⌊biai⌋bi+⌊biai⌋∣yi+1∣⩽ai−⌊biai⌋(bi−∣yi+1∣)
又因为
∣
y
i
+
1
∣
<
∣
a
i
+
1
∣
=
∣
b
i
∣
|y_{i+1}| < |a_{i+1}|=|b_i|
∣yi+1∣<∣ai+1∣=∣bi∣ ,所以
b
i
−
∣
y
i
+
1
∣
>
0
b_i - | y_{i+1} | > 0
bi−∣yi+1∣>0,故
∣
y
i
∣
<
∣
a
i
∣
| y_i | < |a_i|
∣yi∣<∣ai∣ ,满足性质。
根据数学归纳法可得,原方程的解亦满足性质。
六、求解二元一次方程不定方程
接下来我们要求解二元一次方程
a
x
+
b
y
=
c
ax+by=c
ax+by=c 。
①
gcd
(
a
,
b
)
∣
c
\gcd(a,b) \mid c
gcd(a,b)∣c 时,有无穷多组解。
使用扩展欧几里得算法求出方程
a
x
+
b
y
=
gcd
(
a
,
b
)
ax+by=\gcd(a,b)
ax+by=gcd(a,b) 的特解
x
=
x
0
,
y
=
y
0
x=x_0, y=y_0
x=x0,y=y0 后,方程
a
x
+
b
y
=
c
ax+by=c
ax+by=c 的一组特解可以表示为:
x
=
c
gcd
(
a
,
b
)
x
0
,
y
=
c
gcd
(
a
,
b
)
y
0
x=\frac{c}{\gcd(a,b)}x_0,y=\frac{c}{\gcd(a,b)}y_0
x=gcd(a,b)cx0,y=gcd(a,b)cy0
因此,
a
x
+
b
y
=
c
ax+by=c
ax+by=c 的所有解可表示为:
x
=
c
gcd
(
a
,
b
)
x
0
+
b
gcd
(
a
,
b
)
k
,
y
=
c
gcd
(
a
,
b
)
y
0
−
a
gcd
(
a
,
b
)
k
x=\frac{c}{\gcd(a,b)}x_0+\frac{b}{\gcd(a,b)}k, y=\frac{c}{\gcd(a,b)}y_0-\frac{a}{\gcd(a,b)}k
x=gcd(a,b)cx0+gcd(a,b)bk,y=gcd(a,b)cy0−gcd(a,b)ak
其中 k k k 为整数。
② gcd ( a , b ) ∤ c \gcd(a,b) \nmid c gcd(a,b)∤c 时,无解。根据整除性质易证。
七、线性同余方程
形如 a x ≡ c ( m o d b ) ax\equiv c\pmod b ax≡c(modb) 的方程被称为线性同余方程。
八、求解线性同余方程
线性同余方程 a x ≡ c ( m o d b ) ax\equiv c\pmod b ax≡c(modb) 的解与 a x + b y = c ax+by=c ax+by=c 的解等价。同时,这两个方程解的存在性也相同。即当 gcd ( a , b ) ∣ c \gcd(a,b)\mid c gcd(a,b)∣c 时,方程存在无数解,当 gcd ( a , b ) ∤ c \gcd(a,b)\nmid c gcd(a,b)∤c 时,方程无解。
因此采用扩展欧几里得算法求出二元一次不定方程的解,那么这组解也是线性同余方程的解(此时无需关注 y y y 的解是多少,只关注 x x x 的解即可)。