二元一次方程の通项公式

· · 算法·理论

题目背景

某一天,小明在课本上看到了这样一个方程组:

\begin{cases} ax+by=c\\ dx+ey=f \end{cases}

小明不会解,求你来帮他。

解法

现在,我们来推导一元二次方程通项公式:

代入法

ax+by=c 可知,x=\frac{c-by}a

x=\frac{c-by}adx+ey=f 得:

\frac{d(c-by)}a+ey=f

化简得到:

y=\frac{af-cd}{ae-bd}

y=\frac{af-cd}{ae-bd}x=\frac{c-by}a 得:

x=\frac{c-b\frac{af-cd}{ae-bd}}a $$ \begin{cases} x=\frac{c-b\frac{af-cd}{ae-bd}}a \\ y=\frac{af-cd}{ae-bd} \end{cases} $$ 小明看到了你 ~~屎山一样~~ 的求解过程,不太确定,于是代入了 $a=2,b=3,c=8,d=3,e=2,f=7$ 求解,发现 $x=1,y=2$,正确。 ## 消元法 将 $ax+by=c$ 乘上 $\frac da$ 得: $$ dx+\frac{bd}ay=\frac{cd}a $$ 将 $dx+\frac{bd}a=\frac{cd}a$ 减去 $dx+ey=f$ 得: $$ (\frac{bd}a-e)y=\frac{cd}a-f $$ 化简得到: $$ y=\frac{cd-af}{bd-ae} $$ 代 $y=\frac{cd-af}{bd-ae}$ 入 $ax+by=c$ 得: $$ ax+b\frac{cd-af}{bd-ae}=c $$ 化简得: $$ x=\frac{c-b\frac{cd-af}{bd-ae}}a $$ $\therefore$ 原方程式的解为: $$ \begin{cases} x=\frac{c-b\frac{cd-af}{bd-ae}}a \\ y=\frac{cd-af}{bd-ae} \end{cases} $$ 小明傻眼了:两个方法求出来的通项公式为什么不一样诶? 但是实际上我们用消元法求解时得到 $y=\frac{cd-af}{bd-ae}$ 时,将分数右边分子和分母同时乘上 $-1$,数值不变,再求解 $x$,就可以得到和代入法同样的结果。 # Code(使用 `double`) ```cpp #include <bits/stdc++.h> using namespace std; double a, b, c, d, e, f; int main() { while (1) { cout << "请输入 a, b, c, d, e, f 的值,以空格分隔\n"; cin >> a >> b >> c >> d >> e >> f; cout << "x = " << (c - b * (c * d - a * f) / (b * d - a * e)) / a << '\n'; cout << "y = " << (c * d - a * f) / (b * d - a * e) << '\n'; return 0; } } ``` # Code(使用 `frac`) ```cpp #include <bits/stdc++.h> using namespace std; struct frac{ long long x, y; // x / y }; frac operator + (const frac &a, const frac &b) { frac c; c.y = a.y * b.y; c.x = a.x * b.y + a.y * b.x; long long temp = __gcd(c.x, c.y); c.x /= temp, c.y /= temp; if (c.y < 0) { c.x *= -1, c.y *= -1; } return c; } frac operator - (const frac &a, const frac &b) { frac c; c.y = a.y * b.y; c.x = a.x * b.y - a.y * b.x; long long temp = __gcd(c.x, c.y); c.x /= temp, c.y /= temp; if (c.y < 0) { c.x *= -1, c.y *= -1; } return c; } frac operator * (const frac &a, const frac &b) { frac c; c.y = a.y * b.y; c.x = a.x * b.x; long long temp = __gcd(c.x, c.y); c.x /= temp, c.y /= temp; if (c.y < 0) { c.x *= -1, c.y *= -1; } return c; } frac operator / (const frac &a, const frac &b) { frac c; c.y = a.y * b.x; c.x = a.x * b.y; long long temp = __gcd(c.x, c.y); c.x /= temp, c.y /= temp; if (c.y < 0) { c.x *= -1, c.y *= -1; } return c; } frac a, b, c, d, e, f; int main() { while (1) { cout << "请输入 a, b, c, d, e, f 的分子和分母,以空格或换行分隔\n"; cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y >> d.x >> d.y >> e.x >> e.y >> f.x >> f.y; if (!a.y || !b.y || !c.y || !d.y || !e.y || !f.y) { cout << "分母不可以为0!"; continue; } frac x = (c - b * (c * d - a * f) / (b * d - a * e)) / a; frac y = (c * d - a * f) / (b * d - a * e); cout << "x = " << x.x << " / " << x.y << '\n'; cout << "y = " << y.x << " / " << y.y << '\n'; } return 0; } ```