用途

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

基本原理

扩展欧几里得算法基于这样一个原理:若a=bq+r (qZ,r[0,b)Z)a=bq+r\ (q\in \mathbb{Z},r\in [0,b) \cap \mathbb{Z}),且有bx+ry=(b,r) (x,yZ)bx'+ry'=(b,r)\ (x,y\in \mathbb{Z}),则有x=y,y=xqyx=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=xqy\because a=bq+r\ ,x=y',y=x'-qy'
ax+by=(bq+r)y+b(xqy)=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=ccc为任意整数),再依次回代计算xxyy即可。值得注意的是,随着cc取值的变化,计算出的一组解也会变化。
算法的时间复杂度为O(log2n)O(log_{2} n)

具体例子

aabbqqrrxxyy(a,b)(a,b)方程 ax+by=(a,b)ax+by=(a,b)
123451234567867818181411411011011839-18393312345×101+678×(1839)=312345\times 101+678\times (-1839)=3
6786781411414411411421-2110110133678×(21)+141×101=3678\times(-21)+141\times101=3
141141114114112727171721-2133141×17+114×(21)=3141\times 17+114\times (-21)=3
114114272744664-4171733114×(4)+27×17=3114\times (-4)+27\times 17=3
2727664433114-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

上述表格的前44a,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-377977914184-14184
2-255355310069-10069
1-13273275954-5954
001011011839-1839
11125-12522762276
22351-35163916391
33577-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;
}

评论