[VIJOS1003] 等价表达式(表达式解析)
描述
明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。
这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?
这个选择题中的每个表达式都满足下面的性质:
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……
对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。
对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。
格式
输入格式
输入的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……
输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。
输出格式
输出包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。
样例输入1
( a + 1) ^2 3 (a-1)^2+4*a a + 1+ a a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a
样例输出1
AC
表达式解析。标准做法。一个一个值代入验证。要暴力展开就GG了。。。
#include <bits/stdc++.h> using namespace std; const int modn = 1e9 + 7; int term(char *s, int &i, int n, int avalue); int expression(char *s, int &i, int n, int avalue); int primary(char *s, int &i, int n, int avalue); int termpow(char *s, int &i, int n, int avalue); int multiply(int lhs, int rhs) { return (1LL * lhs * rhs) % modn; } int add(int lhs, int rhs) { return (lhs + rhs) % modn; } int subtract(int lhs, int rhs) { return (lhs - rhs + modn) % modn; } int pow(int base, int exp) { if (exp == 0) return 1; if (exp == 1) return base % modn; else { int res = pow(base, exp / 2); res = multiply(res, res); if (exp & 1) res = multiply(res, base); return res; } } int number(char *s, int &i, int n, int avalue) { if (s[i] == 'a') { i++; return avalue; } else { int res = 0; for ( ; i < n && isdigit(s[i]); ++i) res = res * 10 + s[i] - '0'; return res % modn; } } int primary(char *s, int &i, int n, int avalue) { int res; while (i < n && s[i] == ' ') ++i; if (s[i] == '(') { res = expression(s, ++i, n, avalue); ++i; } else if (s[i] == 'a' || isdigit(s[i])) res = number(s, i, n, avalue); return res; } int termpow(char *s, int &i, int n, int avalue) { int res = primary(s, i, n, avalue); while (i < n) { if (s[i] == '^') res = pow(res, primary(s, ++i, n, avalue)); else if (s[i] == ' ') { ++i; continue; } else break; } return res; } int term(char *s, int &i, int n, int avalue) { int res = termpow(s, i, n, avalue); while (i < n) { if (s[i] == '*') res = multiply(res, termpow(s, ++i, n, avalue)); else if (s[i] == ' ') { ++i; continue; } else break; } return res; } int expression(char *s, int &i, int n, int avalue) { int res = term(s, i, n, avalue); while (i < n) { if (s[i] == '+') res = add(res, term(s, ++i, n, avalue)); else if (s[i] == '-') res = subtract(res, term(s, ++i, n, avalue)); else if (s[i] == ' ') { ++i; continue; } else break; } return res; } int evaluate(char* s, int avalue) { int n = strlen(s); int it = 0; int res = expression(s, it, n, avalue); } char tmplate[500]; char match[40][500]; bool ans[40]; int N; int main() { #ifdef ULTMASTER freopen("a.in","r",stdin); #endif gets(tmplate); scanf("%d\n", &N); for (int i = 0; i < N; ++i) { ans[i] = 1; gets(match[i]); } for (int i = 0; i <= 10000; ++i) { int tmp = evaluate(tmplate, i); for (int j = 0; j < N; ++j) if (evaluate(match[j], i) != tmp) ans[j] = 0; } for (int i = 10000000; i <= 10010000; ++i) { int tmp = evaluate(tmplate, i); for (int j = 0; j < N; ++j) if (evaluate(match[j], i) != tmp) ans[j] = 0; } for (int i = 0; i < N; ++i) if (ans[i]) putchar('A' + i); putchar('\n'); return 0; }