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