一、题目描述
已知下列表达式
输入包含多组数据,每组数据有两行,第一行是单个整数X,第二行是表达式。要求输出表达式的值 f(x)。保证中间结果在 -1 000 000 000 到 1 000 000 000 之间。输入结束标志 EOF。
样例:
输入
3
1003X^5 +234X^4 -12X^3 -2X^2+987X-1000
(由于CSDN的输入格式的问题,被迫加了些空格防止数字被上标,实际上输入没有空格)
输出
264302
二、算法分析说明与代码编写指导
输入X后要先吞掉紧随其后的回车,否则fgets不能正确读入表达式。
本题的高次项比低次项先输入,因此第一项是最高次的。
设字符串 s 用于保存输入的表达式,c 代表每一项的系数(coefficient),最终答案为 ans ,每项的次数为 Exp(exponent),最高次项的次数为 Expm ,pwr 为从 x 的 1 次方到 Expm 次方的全部值,p 为读取光标,op 为运算符(operator),readx 表示读取每一项时是否已经读到 x 。
对第一项的处理与之后的项稍有不同,所以先读取第一项。系数 c 和次数 Exp 都默认为 1 。
如果最开头是负号,就把运算符 op 改成负号(默认是正),并移动光标到下一个字符。
然后读取系数,保存到 c 中。
接下来,需要判断第一项是常数项还是含 x 的项。如果读到 x ,就移动光标读取 ^ 符号后的次数。如果没有 ^ 符号,就直接移动光标准备读取运算符和下一项。根据 op 来决定第一项的值是正是负。最高次项大于 1 时,就计算 x 从 2 到最高次方的值并保存,这样后续计算的时候就可以直接取相应的结果,无需重复计算。
第一项也有可能是常数,所以需要单独处理一下这种情况。
接下来写一个循环来计算剩下的项的值。这时候光标停在第一项与第二项之间的位置,就是那个运算符上。当然如果只有一项的话,这个位置就是换行符 \n 。这时候直接退出循环并输出即可。如果不是换行,就移动光标准备读取下一项。同样,系数 c 和指数 Exp 都要重设为 1 ,并将 readx 重设为 false ,然后重复第一项的读取方式即可。当然这里直接取前面已经计算过的 x 的 Exp 次幂的结果再乘系数就可以了。注意处理常数项的情形。
读到换行符,循环结束,输出。本例不用将 pwr 数组清零。
三、测试数据
3
X
3
-X
3
2X
3
-2X
3
X^2
3
-X^2
3
2X^2
3
-2X^2
3
-X4+2X3
3
2X5-3X4
3
0
3
1
3
-1
3
X+1
3
-X^2+1
3
2X^3+1
四、AC 代码(0 ms)
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
#pragma warning(disable:4996)
char s[65536]; int x, c, ans, Exp, Expm, pwr[32], p; char op; bool readx;
int main() {
for (;;) {
if (scanf("%d", &x) == EOF)return 0;
getchar(); fgets(s, 65535, stdin);
p = 0, c = 1, Exp = 1, Expm = 1, ans = 0, pwr[1] = x, op = '+', readx = false;
if (s[p] == '-') { op = '-'; ++p; }
if (isdigit(s[p])) { c = 0; while (isdigit(s[p])) { c = c * 10 + s[p] - 48; ++p; } }
if (s[p] == 'X') {
readx = true;
if (s[p + 1] == '^') {
p += 2, Expm = 0; while (isdigit(s[p])) { Expm = Expm * 10 + s[p] - 48; ++p; }
for (int i = 2; i <= Expm; ++i) { pwr[i] = pwr[i - 1] * x; }
}
else { ++p; }
if (op == '+')ans += c * pwr[Expm]; else ans -= c * pwr[Expm];
}
if (readx == false) { if (op == '+')ans += c; else ans -= c; }
for (;;) {
op = s[p]; if (op == '\n')break;
++p, c = 1, Exp = 1, readx = false;
if (isdigit(s[p])) { c = 0; while (isdigit(s[p])) { c = c * 10 + s[p] - 48; ++p; } }
if (s[p] == 'X') {
readx = true;
if (s[p + 1] == '^') {
p += 2, Exp = 0; while (isdigit(s[p])) { Exp = Exp * 10 + s[p] - 48; ++p; }
}
else { ++p; }
if (op == '+')ans += c * pwr[Exp]; else ans -= c * pwr[Exp];
}
if (readx == false) { if (op == '+')ans += c; else ans -= c; }
}
printf("%d\n", ans);
}
}