用途

求解裴蜀方程ax+by=(a,b)ax+by=(a,b)的一组解,其中a,b∈N+a,b\in \mathbb{N_{+}}。

基本原理

扩展欧几里得算法基于这样一个原理:若a=bq+r (q∈Z,r∈[0,b)∩Z)a=bq+r\ (q\in \mathbb{Z},r\in [0,b) \cap \mathbb{Z}),且有bx′+ry′=(b,r) (x,y∈Z)bx'+ry'=(b,r)\ (x,y\in \mathbb{Z}),则有x=y′,y=x′−qy′x=y',y=x'-qy'满足ax+by=(a,b)ax+by=(a,b)。证明如下:

∵bx′+ry′=(b,r) ,(a,b)=(b,r)\because bx'+ry'=(b,r)\ , (a,b)=(b,r)
∴bx′+ry′=(a,b)\therefore bx'+ry'=(a,b)
∵a=bq+r ,x=y′,y=x′−qy′\because a=bq+r\ ,x=y',y=x'-qy'
∴ax+by=(bq+r)y′+b(x′−qy′)=bx′+ry′\therefore ax+by=(bq+r)y'+b(x'-qy')=bx'+ry'
∴ax+by=(a,b)\therefore ax+by=(a,b)

计算过程

先执行欧几里得算法的一般过程,得到b=0b=0的一步时有平凡解x=1,y=cx=1,y=c(cc为任意整数),再依次回代计算xx和yy即可。值得注意的是,随着cc取值的变化,计算出的一组解也会变化。
算法的时间复杂度为O(log2n)O(log_{2} n)。

具体例子

aabbqqrrxxyy(a,b)(a,b)方程 ax+by=(a,b)ax+by=(a,b)
12345123456786781818141141101101−1839-18393312345×101+678×(−1839)=312345\times 101+678\times (-1839)=3
67867814114144114114−21-2110110133678×(−21)+141×101=3678\times(-21)+141\times101=3
1411411141141127271717−21-2133141×17+114×(−21)=3141\times 17+114\times (-21)=3
11411427274466−4-4171733114×(−4)+27×17=3114\times (-4)+27\times 17=3
272766443311−4-43327×1+6×(−4)=327\times 1+6\times (-4)=3
663322000011336×0+3×1=36\times 0+3\times 1=3
33001100333×1+0×0=33\times 1+0\times 0=3

上述表格的前44列a,b,q,ra,b,q,r是自上而下计算的,x,y, (a,b)x,y,\ (a,b)是由下而上递推的。
上述a=12345,b=678a=12345,b=678的例子中,不断改变cc的取值,计算出的x,yx,y的值如下表。

ccxxyy
−3-3779779−14184-14184
−2-2553553−10069-10069
−1-1327327−5954-5954
00101101−1839-1839
11−125-12522762276
22−351-35163916391
33−577-5771050610506
上表相邻两行xx的差为226226,恰为678(12345,678)\frac{678}{(12345,678)};yy的差为41154115,恰为12345(12345,678)\frac{12345}{(12345,678)}。

解的特征

下面分析cc的取值对解的影响。可以证明,若令取c=0c=0时计算出的一组解为(x0,y0)(x_{0},y_{0}),且辗转相除过程中进行除法运算的次数为nn,则计算出的解为x=(−1)n+1cb(a,b)+x0,y=(−1)nca(a,b)+y0x=(-1)^{n+1}c\frac{b}{(a,b)}+x_{0},y=(-1)^{n}c\frac{a}{(a,b)}+y_{0}。

再来看解的符号。x0x_{0}的符号和(−1)n(-1)^{n}相同,y0y_{0}的符号和(−1)n+1(-1)^{n+1}相同。当c<0c<0时,x,yx,y的符号分别和x0,y0x_{0},y_{0}相同;当c>0c>0时,x,yx,y的符号分别和x0,y0x_{0},y_{0}相反。

程序代码

下面程序中取c=0c=0,即上表的情形。实际编写程序时只需使用工具函数exgcd(a,b,x,y)即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
int exgcd(int a,int b,int &x,int &y);
int main(void){
int a,b,d,x,y;
cin >> a >> b;
d=exgcd(a,b,x,y);
cout << "裴蜀方程" << a << "x+" << b << "y=" << d;
cout << "的一组解是" << "x=" << x << "y=" << y << endl;
return 0;
}
int exgcd(int a,int b,int &x,int &y){
int xx,yy,d,q,r; //xx是x',yy是y',d是(a,b)
if (b==0){
x=1,y=0;
return a;
}
q=a/b,r=a%b; //a=bq+r
d=exgcd(b,r,xx,yy);
x=yy,y=xx-q*yy;
return d;
}

评论