一、首先系统的说一下扩展欧几里得求解线性方程的过程:
用扩展欧几里得接线性方程:ax + by = c; (1)
用扩展欧几里得先求:ax + by = gcd(a, b);(2)得到解x0,y0
对这一组解x0, y0得到方程(1)的解:如果c不是gcd(a,b)的倍数,方程(1)无解,
否则有解, 另 a1 = a/gcd(a,b) , b1 = b/gcd(a,b);
{ x1 = x0 * (c/gcd(a,b))+ kb1
解为:
{ y1 = y0 * (c/gcd(a,b)) - ka1
二、然后为什么通解是那样得到的?
1、下面具体说一下,先说扩展欧几里得求解ax + by = gcd(a, b):
若ax1 + by1 = gcd(a, b)有解,那么bx2 + (a%b)y2 = gcd(b, a%b)同样有解。
且 gcd(a, b) = gcd(b, a%b);
所以ax1 + by1 = bx2 + (a%b)y2
a%b = a - a/b*b ---------------------这里的除号是整除
因此又 可以变形为 bx2 + (a%b)y2 = bx2 - (a - a/b*b) * y2 = ay2 + b * (x2 - a/b*y2)
所以:ax1 + by1 = ay2 + b * (x2 - a/b*y2)
两边相等
{ x1 = y2
即 :
{ y1 = x2 - a/b*y2
因此当知道x2, y2时可以求x1, y1
如果使用欧几里得递归求d = gcd(a, b)的话,当最后状态就是 d*x + 0*y = gcd(a, b);
所以令x = 1, y = 0, 递归回到上一层就可以求出上一层的x,y了,因此可以用扩展的欧几里得求解线性方程组。
2、再说一下怎么得到方程(1)的一个解:
可以看到 x0, y0是 ax + by = gcd(a, b) 式的解,将 ax + by = gcd(a, b) 式转化一下:
(两边同乘以c/gcd(a,b)) a* x * c/gcd(a,b) + b * y * c/gcd(a,b) = c =>
即比较(3)式和(1)式可知:
{ ax + by = c; (1)
比较:
{a * x * c/gcd(a,b) + b * y * c/gcd(a,b) = c (3)
满足(3)式的解的x0, y0同乘以 c/gcd(a, b) 就是(1)式的解。
3、最后说一下说怎么得到的(1)式通解:
a * x2 * c/gcd(a,b) + b * y2 * c/gcd(a,b) = c = a * x3 * c/gcd(a,b) + b * y3 * c/gcd(a,b)
整理得:
a *( x2 * c/gcd(a,b) - x3 * c/gcd(a,b) ) = b * ( y3 * c/gcd(a,b) - y2 * c/gcd(a,b) )
因为 a,b的最大公约数为 gcd(a,b)约去后分别记为 a1, b1;
所以=》 a1 *( x2 * c/gcd(a,b) - x3 * c/gcd(a,b) ) = b1 * ( y3 * c/gcd(a,b) - y2 * c/gcd(a,b) )
所以上式要存在整数解,则令 : x2 * c/gcd(a,b) - x3 * c/gcd(a,b) = k * b1 k属于整数 (4)
所以=》 a1 * k * b1 = b1 * ( y3 * c/gcd(a,b) - y2 * c/gcd(a,b) ) =》
a1 * k = y3 * c/gcd(a,b) - y2 * c/gcd(a,b) (5)
(4)、(5)变形即得通解:
{ x2 = x3 * (c/gcd(a,b))+ kb1
且解满足:
{ y2 = y3 * (c/gcd(a,b))- ka1
所以解出一组(x , y),代入上式既得(1)式的通解。
三、扩欧的应用及模板:
得出ax + by = gcd(a, b)的解x1,x2或无解
1、而ax + by = c 的解在ax + by = gcd(a, b)有解的情况下,一般求解x最小正整数解:
可以由此得到: x = (x0 * ( c/gcd(a,b) ) ) % b1 + b1 ) % b1;
2、还可以用来求乘法逆元:
乘法逆元为:ax = 1(mod p)意思为:(a*x) % p = 1
a 和 x 互为 mod 的 乘法逆元, 因为上式可变形为: ax = kp + 1 ==》 ax - kp = 1 ==》 a*x + (-k)*p = 1,可见当gcd(a,p) == 1时,即a , p互质时方程有解接出的x即为a mod p时的乘法逆元,而一般求出来的时候有可能为负数,所以要变换一下:
x = (x0 * ( c/gcd(a,b) ) ) % b1 + b1 ) % b1;即的解。
代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
void k_GCD(int a, int b, int &d, int &x, int &y)
{
if(!b)
{
d = a, x = 1, y = 0;
}
else
{
k_GCD(b, a%b, d, y, x);
y -= x*(a/b);
}
}
int main()
{
int a, b, c, d, x, y;
scanf("%d%d%d", &a, &b, &c);
k_GCD(a, b, d, x, y);
if(c % d == 0)
{
x *= (c/d);
y *= (c/d);
if(x < 0)
{
int a0, b0;
a0 = a / d;
b0 = b / d;
//b0 = b0 < 0 ? -b0 : b0;
while(x < 0)
{
x += b0;
y -= a0;
}
}
printf("%d %d %d\n", x, y, d);
}
else
printf("无解!\n");
return 0;
}