问题:ax+by=c,已知a、b、c,求解使该等式成立的一组x,y。其中a、b、c、x、y均为整数
a,b的最大公约数为gcd(a,b)。如果c不是gcd(a,b)的倍数,则该等式无解,因为等式左边除以gcd(a,b)是整数,而等式右边除以gcd(a,b)后为小数。
因此,只有当c是gcd(a,b)的倍数的时候,该等式有解。这样,可以通过计算使ax1+by1=gcd(a,b)成立的x1、y1,然后有x=(c/gcd(a,b))*x1,y=(c/gcd(a,b))*y1,得到x,y。
问题就被转换为求使ax+by=gcd(a,b)成立的一组x,y。这可以用扩展欧几里德算法求解。如下:
如果b为零,则gcd(a,b)=a,那么x=1,y=0为一组解。
如果b不为零,根据欧几里德定理,可以设
ax1+by1=gcd(a,b)=gcd(b,a%b)=bx2+(a%b)y2=bx2+(a-(a/b)*b)y2
化简后有x1=y2,y1=x2-(a/b)y2。因此x1,y1依赖于x2,y2,同理依次类推递归调用求出x3,y3,x4,y4……,类似于辗转相除,直到b=0时,求出xn,yn,便可以推出x1,y1的值。
扩展欧几里德算法:
// 结果存储在x,y中,用户调用时保证a、b、c都是整数
// 返回a,b的最大公约数
int extended_euclid( int a, int b, int & x, int & y)
{
if (b == 0 ) // gcd(a, b) == a
{
x = 1 ;
y = 0 ;
return a;
}
int n = extended_euclid(b, a % b, x, y);
int tmp = x;
x = y;
y = tmp - static_cast < int > (a / b) * y;
return n;
}
用户调用linear_equation求解线性方程:
// 解该线性方程等同于解同余式ax = c(mod b)
// 返回值表示是否有解,true有解,false无解
bool linear_equation( int a, int b, int c, int & x, int & y)
{
int n = extended_euclid(a, b, x, y);
if (c % n)
return false ;
int k = c / n;
x *= k;
y *= k;
return true ;
}
linear_equation函数也可以用来解同余式ax=c(mod b)。
由ax=c(mod b),可以得到ax = mb+r;c = nb+r。化简可以得到ax+(n-m)b=c。调用linear_equation可以求出x。