解 方 程 ( 洛 谷 P 1022 ) \mathcal{解方程(洛谷P1022)} 解方程(洛谷P1022)
题目大意
对于一个一元一次方程,其中:
- 包含整数、小写字母及 + 、 − 、 = +、-、= +、−、= 这三个数学符号(当然,符号 − - − 既可作减号,也可作负号)。
- 方程中并没有括号
- 方程中的字母表示未知数
- 有唯一实数解。(精确至小数点后三位)
解题思路
这道题思维难度和代码难度都不大,就是细节处理有点麻烦,需要判断一些特殊
情况(比如
−
0.0
{\color{RED}-0.0}
−0.0 什么的)。那我就直接上代码思路了。
因为是一元一次方程,所以最终一定可以化成
k
x
+
b
=
0
kx+b=0
kx+b=0 的形式,整理可得
x
=
−
b
k
x=-\frac{b}{k}
x=−kb ,为了减少变量数 方便,将等号右边的多项式直接移到等式左边,即系数均乘 -1,可以用一个变量
n
o
w
now
now 标记一下。
首先大致考虑一下思考的方向,一元一次方程的所有类型:
-
毒
瘤
1
\color{RED}毒瘤1
毒瘤1 +x,−x,例如:
- 4 + x = 8 4+x=8 4+x=8
- − 5 − y = 0 −5−y=0 −5−y=0
- − a = a / a = − a -a=a/a=-a −a=a/a=−a
-
毒
瘤
2
\color{RED}毒瘤2
毒瘤2 未知数前带有一个数,+3x,-3x,+0x,-0x,例如:
- 4 + 3 x = 8 4+3x=8 4+3x=8
- 4 − 3 z = 8 4−3z=8 4−3z=8
- 4 + 0 x = 4 4+0x=4 4+0x=4, 6 a − 5 + 1 = 2 − 2 a 6a−5+1=2−2a 6a−5+1=2−2a
- 毒 瘤 3 \color{RED}毒瘤3 毒瘤3 − x = 0 −x=0 −x=0,由之前的做法解得 x = − 0.000 x=-0.000 x=−0.000,正确解是 x = 0.000 x=0.000 x=0.000,原因是 0 0 0 除以负数会被计算成 − 0.0 -0.0 −0.0,所以需要特判一下。
学废了吗
接下来就很简单了
做法:
-
关于数字的读入
if (c >= '0' && c <= '9') { x = x * 10 + c - '0'; }
若判定为数字则叠加当前项系数。
-
对于符号 ‘+’,‘-’,‘=’ 的处理
if (c == '+') { b += now * op * x; x = 0; op = 1; } if (c == '-') { b += now * op * x; x = 0; op = -1; } if (c == '=') { b += now * op * x; x = 0; op = 1; now = -1; }
这里 b b b 为常数部分的值; n o w now now 表示相对等号的位置,左边为 1 1 1 ,右边为 − 1 -1 −1; o p op op 表示项的系数的正负性, x x x 则是项的系数。
读到加号,常数累加,系数清零,符号标记为正,减号同理。读到等号则需额外将 n o w now now 改为 − 1 -1 −1。
-
关于未知数的处理
if (c >= 'a' && c <= 'z') { k += now * op * x; x = 0; a = c; res = 0; }
若判定为小写字母,则将未知数的系数累加,项系数清零,并标记未知数名 a a a。
-
解决 毒 瘤 1 \color{RED}毒瘤1 毒瘤1
那还不简单,没有读进数就默认乘 1 就好了嘛
if (c >= 'a' && c <= 'z') { x ? k += now *f *x : k += now * f * 1; x = 0; a = c; }
-
解决 毒 瘤 2 \color{RED}毒瘤2 毒瘤2
这就需要引入一个新的变量 r e s res res 来标记是否有系数的读入。至于 r e s res res 的处理,只需要在读到数字时将 r e s res res 置为 1 1 1 ,读到其它字符都将 r e s res res 置为 0 0 0 就行了。
if (c >= 'a' && c <= 'z') { if (res) { k += now * op * x; x = 0; } else k += now * op; a = c; res = 0; } else if (c >= '0' && c <= '9') { x = x * 10 + c - '0'; res = 1; } else if (c == '+') { b += now * op * x; x = 0; op = 1; res = 0; } else if (c == '-') { b += now * op * x; x = 0; op = -1; res = 0; } else if (c == '=') { b += now * op * x; x = 0; op = 1; now = -1; res = 0; }
-
解决 毒 瘤 3 \color{RED}毒瘤3 毒瘤3
那还不简单if (ans == -0) ans = 0;
A C c o d e AC \ code AC code
#include <bits/stdc++.h>
using namespace std;
int op = 1, now = 1, k, x, b;
char a, c;
bool res;
double ans;
signed main()
{
c = getchar();
while (1)
{
if (c >= 'a' && c <= 'z')
{
if (res)
{
k += now * op * x;
x = 0;
}
else
k += now * op;
a = c;
res = 0;
}
else if (c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
res = 1;
}
else if (c == '+')
{
b += now * op * x;
x = 0;
op = 1;
res = 0;
}
else if (c == '-')
{
b += now * op * x;
x = 0;
op = -1;
res = 0;
}
else if (c == '=')
{
b += now * op * x;
x = 0;
op = 1;
now = -1;
res = 0;
}
else
{
b += now * op * x;
break;
}
c = getchar();
}
ans = (double)-b / k;
if (ans == -0)
ans = 0;
printf("%c=%.3lf", a, ans);
return 0;
}