【问题标题】:Solving a simple linear equation求解一个简单的线性方程
【发布时间】:2015-02-25 05:44:02
【问题描述】:
假设我需要解以下方程,
ax + by = c
其中a、b 和c 是已知值,x、y 是介于 0 和 10(含)之间的自然数。
除了平凡的解决方案,
for (x = 0; x <= 10; x++)
for (y = 0; y <= 10; y++)
if (a * x + b * y == c)
printf("%d %d", x, y);
...有没有办法有效地找到这个独立系统的所有解决方案?
【问题讨论】:
标签:
algorithm
linear-algebra
linear-equation
【解决方案1】:
在您的情况下,由于 x 和 y 只取 0 和 10 之间的值,因此蛮力算法可能是最佳选择,因为它需要更少的时间来实现。
但是,如果您必须在更大的范围内找到所有积分解 (x, y) 对,您确实应该使用正确的数学工具来解决这个问题。
您正在尝试求解线性丢番图方程,并且众所周知,当且仅当 a 和 b 的最大公约数 d 除以 c 时,积分解才存在 em>。
如果解决方案不存在,那么你就完成了。否则,您应该首先应用Extended Euclidean Algorithm 来找到方程ax + by = d 的特殊解。
根据Bézout's identity,所有其他积分解的形式为:
其中k 是任意整数。
但请注意,我们对ax + by = c 的解决方案感兴趣,我们必须将所有(x, y) 对缩放c / d 的系数。
【解决方案2】:
你只需要遍历 x,然后计算 y。 (x, y) 是一个解,如果 y 是整数,并且在 0 到 10 之间。
在 C 中:
for (int x = 0; x <= 10; ++x) {
double y = (double)(c - ax) / b;
// If y is an integer, and it's between 0 and 10, then (x, y) is a solution
BOOL isInteger = abs(floor(y) - y) < 0.001;
if (isInteger && 0 <= y && y <= 10) {
printf("%d %d", x, y);
}
}
【解决方案3】:
您可以通过直接检查(c-a*x)/b 是否为整数来避免第二个for 循环。
编辑:由于我在 cmets 中指出的一些粗心疏忽,我的代码没有我希望的那么干净,但它仍然比嵌套的 for 循环快。
int by;
for (x = 0; x <= 10; x++) {
by = c-a*x; // this is b*y
if(b==0) { // check for special case of b==0
if (by==0) {
printf("%d and any value for y", x);
}
} else { // b!=0 case
y = by/b;
if (by%b==0 && 0<=y && y<=10) { // is y an integer between 0 and 10?
printf("%d %d", x, by/b);
}
}
}