【NOIP模拟题】【表达式求值】2016.11.11第三题equal题解

来源:互联网 发布:液晶电视编程器那种好 编辑:程序博客网 时间:2024/06/05 15:49
3.equal
【问题描述】
明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。
这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?
这个选择题中的每个表达式都满足下面的性质:
1. 表达式只可能包含一个变量‘a’。
2. 表达式中出现的数都是正整数,而且都小于10000。
3. 表达式中可以包括四种运算‘+’(加),‘-’(减),‘*’(乘),‘^’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘^’,然后是‘*’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)
4. 幂指数只可能是1到10之间的正整数(包括1和10)。
5. 表达式内部,头部或者尾部都可能有一些多余的空格。
下面是一些合理的表达式的例子:
((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)^3,1^10^9……
【输入文件】
输入文件equal.in的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……
输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。
【输出文件】
输出文件equal.out包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。
【样例输入】
( a + 1) ^2
3
(a-1)^2+4*a
a + 1+ a
a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a
【样例输出】
AC
【数据规模】
对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。

对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。


这道题是2005年的原题,不知道怎么搞出了无法编译。下面对的,测评机怎么改都编译不起,GG......

最后乱搞找了原来写的。

代码如下:

#include<cmath>#include<cctype>#include<vector>#include<string>#include<sstream>#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int a1(666), a2(233), p(10e9+7);struct Node {int lc, rc;long long num;char op;Node(long long n, char o = '?', int l = -1, int r = -1): op(o), lc(l), rc(r), num(n) {}};vector<Node>tree;int build(string::iterator left, string::iterator right) {if (string(left, right).find_first_of("*()+-/^") == string::npos) { stringstream ss(string(left, right));int tmp;ss >> tmp;tree.push_back(Node(tmp));return tree.size() - 1;}int parentheses(0), c1(-1), c2(-1), c3(-1);for (int i(0); i < right - left; ++i)switch (*(left + i)) {case '(':++parentheses;break;case ')':--parentheses;break;case '+':case '-':if (!parentheses)c1 = i;break;case '*':case '/':if (!parentheses)c2 = i;break;case '^':if (!parentheses)c3 = i;}if (c1 < 0)c1 = c2;if (c1 < 0)c1 = c3;if (c1 < 0)return build(left + 1, right - 1);tree.push_back(Node(0, *(left + c1), build(left, left + c1),build(left + c1 + 1, right)));return tree.size() - 1;}long long q_pow(long long base, long long index) {long long ans(1);for (; index; index >>= 1ll, base = ((base % p) * (base % p)) % p)if (index & 1ll)ans = ((ans % p) * (base % p)) % p;return ans % p;}void calculate(int node) {if (tree[node].lc < 0)return;calculate(tree[node].lc);calculate(tree[node].rc);long long a(tree[tree[node].lc].num), b(tree[tree[node].rc].num);switch (tree[node].op) {case '+':a = (a % p + b % p) % p;break;case '-':a = (a % p - b % p + p) % p;break;case '*':a = ((a % p) * (b % p)) % p;break;case '/':a /= b;break;case '^':a = q_pow(a, b);}tree[node].num = a;tree[node].lc = tree[node].rc = -1;}long long work(string expr, const int a) {tree.clear();stringstream ss;ss << a;for (size_t i(0); i < expr.size(); ++i)switch (expr[i]) {case 'a':expr.replace(i, 1, ss.str());break;case ' ':expr.erase(i--, 1);break;case '-':if (!i || string("+-*/^(").find(expr[i - 1]) != string::npos)expr.insert(i, "0");}int lp(count(expr.begin(), expr.end(), '(')),rp(count(expr.begin(), expr.end(), ')'));if (lp - rp)if (lp > rp)expr += string(lp - rp, ')');elseexpr.insert(0, rp - lp, '(');build(expr.begin(), expr.end());calculate(tree.size() - 1);return tree.rbegin()->num;}int main() {freopen("equal.in","r",stdin);freopen("equal.out","w",stdout);string expression;getline(cin, expression);int n;cin >> n;cin.ignore(512, '\n');vector<string>options(n);for (int i(0); i < n; ++i)getline(cin, options[i]);long long std1(work(expression, a1)), std2(work(expression, a2));for (size_t i(0); i < options.size(); ++i)if (work(options[i], a1) == std1 && work(options[i], a2) == std2)cout.put('A' + i);cout << endl;return 0;}

距离NOIP还有8天,然而今天与前几天的的发挥不同,只有30分。对知识熟练度及考试策略等再作调整。

谨记谨记!


0 0