相信你们对欧几里得算法,即展转相除法不陌生吧。算法
代码以下:spa
int gcd(int a, int b){ return !b ? gcd(b, a % b) : a; }
而扩展欧几里得算法,顾名思义就是对欧几里得算法的扩展。blog
切入正题:递归
首先咱们来看一个问题:class
求整数x, y使得ax + by = 1, 若是gcd(a, b) != 1, 咱们很容易发现原方程是无解的。则方程ax + by = 1有正整数对解(x, y)的必要条件是gcd(a, b) = 1,即a, b 互质。扩展
此时正整数对解(x, y)能够经过扩展欧几里得算法求得。gc
对于方程ax + by = gcd(a, b);咱们设解为x1, y1im
咱们令a = b, b = a % b;img
获得方程bx + a % by = gcd(b, a % b);计算机
由欧几里得算法能够获得gcd(a, b) = gcd(b, a % b);
代入可得:bx + a % b y = gcd(a, b)
设此方程解为x2, y2;
在计算机中咱们知道: a % b = a - (a / b) * b;
代入方程化解得:
ay2 + b(x2 - (a / b) y2) = gcd(a, b);
与ax1 + by1 = gcd(a, b) 联立,咱们很容易得:
x1 = y2, y1 = x2 - (a / b)y2;
而后咱们就这样能够解出来了。
等等咱们彷佛忘记一个东西了吧?对就是递归的终点。也就是最后方程的解x和y。
对于方程ay2 + b(x2 - (a / b) y2) = gcd(a, b);
当b = 0时,发现a * 1 + b * 0 = gcd(a, b)
则有x = 1, y = 0。
由此咱们把ax + by = 1的其中一组解解出来了, 仅仅是其中一组解。
对于已经获得的解x1, y1;咱们即可以求出通解。
咱们设x = x1 + kt;t为整数
带入方程解得y = y1 - a * k / b * t;
而咱们要保证y也为整数的话必须保证a * k /b也为整数,咱们不妨令k = b/gcd(a, b);
因此通解为:
x = x1 + b / gcd(a, b) * t;
y = y1 - a / gcd(a, b) * t;
其中t为整数。
附上伪代码:
int a, b, x, y; int extgcd(int a, int b,int &x, int &y){ int d = a; if(b != 0){ d = extgcd(b, a % b, y, x); y -= (a / b) * x; } else x = 1, y = 0; return d; }//d = gcd(a, b);
扩展欧几里得算法还能够用来解以下方程:
ax = mt + b,ax - mt = b
这种形式不就是前面的形式吗?