It has been 536 days since the last update, the content of the article may be outdated.
扩展欧几里德定理
引入
对于不定方程 ax+by=c,如果我们想求出它的整数解,我们就可以使用扩展欧几里德定理(exgcd)。
前置知识
裴蜀定理
定义
设 a, b 是不全为零的整数,则存在整数 x, y 使得 ax+by=gcd(a,b).
证明
- 当 a=0 或 b=0 时,原式显然成立
- 当 a,b 都不等于 0 时
- 记集合 S={ax+by∣x,y∈Z且ax+by>0}
- 设 d=ax0+by0 为 S 中的最小正整数,现在只需证明 d=gcd(a,b)即可
- 设 a=qd+r,其中 q,r 分别为 a/d 的商和余数,则有
- r=a−qd=a−q(ax0+by0)=a(1−qx0)+b(−qy0),注意到形式一致,说明 r 也是 S 中的元素,又 d 为最小正整数,故 r=0 ,即 d∣a
- 同理可得,d∣b ,故 d∣gcd(a,b),又 gcd(a,b)∣ax0+by0 ,故 d=gcd(a,b),证毕
扩展欧几里德定理
接下来,让我们讲解一下扩展欧几里德定理(exgcd):
- 设 ax1+by1=gcd(a,b),bx2+(a mod b)y2=gcd(b,a mod b)
- 由欧几里德定理可知,gcd(a,b)=gcd(b,a mod b),且 a mod b=a−⌊a/b⌋∗b
- 故 ax1+by1=bx2+(a−⌊a/b⌋∗b)y2=ay2+b(x2−⌊a/b⌋y2)
- 故x1=y2,y1=x2−⌊a/b⌋y2,到这里,我们遍可以递归求解了,注意退出条件:当 b=0 时,x=1,y=0
核心代码如下:
1 2 3 4 5 6 7 8 9 10
| void exgcd(int a, int b, int &x, int &y) { if(!b) { x = 1; y = 0; } exgcd(b, a%b, y, x); y -= a/b * x; }
|
可能有人会问:y -= a/b * x
是什么意思呢?
- 我们不妨假设递归结束时 x=xn,y=yn ,那么退回到上一层后有:yn−1=xn,xn−1=yn
- 由前文我们知道,xn−1=yn,yn−1=xn−⌊a/b⌋yn,所以退回上一层后 xn−1 直接被求得
- 而对于 yn−1 ,我们发现 xn=yn−1 ,yn=xn−1,所以 yn−1=yn−1−⌊a/b⌋xn−1 ,即原代码所示
延伸
现在我们通过扩展欧几里德定理求出了原方程的一组解,那我们能不能求出其通解呢?答案是可以的
- 设exgcd求出的一组解为 (x1,y1) ,待求的另一组解为 (x2,y2)
- 则有 ax1+by1=ax2+by2 ,整理得 a(x1−x2)=b(y2−y1)
- 两边同时除以 gcd(a,b),得 a′(x1−x2)=b′(y2−y1),其中 a′=a/gcd(a,b),b′=b/gcd(a,b)
- 由于 a′ 与 b′ 互质,故 x1−x2 为 b′ 的整数倍,即 x1−x2=kb′ ,故 x2=x1−kb′ ,同理,y2=y1+ka′
- 故原方程的通解为 x=x1−kb/gcd(a,b) ,y=y1+ka/gcd(a,b)