计蒜客 表达式 (递归)
**链接 : ** Here!
**思路 : **
-
这里采用一种非常风骚的写法, 对于求解表达式来说, 普通的做法就是用栈, 但是还可以利用递归来解决, 其实思考一下, 递归也是调用的系统栈, 所以说本质上并没有什么区别.
-
首先, 设置优先级
- "(", ")" 的优先级最高, 设置为100
- "^" 的优先级次之, 设置为3
- "*", "/" 的优先级再次之, 设置为2
- "+", "-" 的优先级最低, 设置为1
-
当传入一个字符串后, 给字符串中的所有运算符标记优先级等级, 然后选出来优先级最低的运算符, 因为优先级最低的运算符一定是最后计算, 因此就可以将一个表达式拆分成两个子表达式, 因此这就将大问题转化为等价的小问题, 递归解决即可
-
这道题目中有变量 $a$ , 那么这该如何处理呢 ? 我们可以将 $a$ 替换为其他数字, 只要最后计算的结果相同就可以认为两个表达式是等价的,
-
注意 :
- 幂运算的数值可能非常大, 因此需要进行取模, 这里的 $MOD = 1e9 + 7$, 如果遇到乘法的话很可能超出 $int$ 的范围, 因此用 $longlong $ 来存储计算值.
- 选用什么值来替换 $a$ 也是需要注意的一个地方.
代码 :
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define INF 1e9
typedef long long ll;
const int MOD = 1e9 + 7;
ll quick_pow(ll a, ll b) {
ll ret = 1;
while (b) {
if (b & 1) ret = ret * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ret % MOD;
}
// [st, ed)
ll cal_num(char *str, int st, int ed, int a) {
int priority = 0;
int opt_num = 0;
int cur_priority = 0, min_priority = INF, min_pos = -1;
for (int i = st ; i < ed ; ++i) {
if (str[i] == '(') {priority += 100; continue;}
else if (str[i] == ')') {priority -= 100; continue;}
else if (str[i] == '+') cur_priority = priority + 1;
else if (str[i] == '-') cur_priority = priority + 1;
else if (str[i] == '*') cur_priority = priority + 2;
else if (str[i] == '^') cur_priority = priority + 3;
else continue;
++opt_num;
if (cur_priority <= min_priority) {
min_priority = cur_priority;
min_pos = i;
}
}
if (opt_num == 0) {
ll temp = 0;
for (int i = st ; i < ed ; ++i) {
if (str[i] == 'a') return a;
if (str[i] < '0' || str[i] > '9') continue;
temp = temp * 10 + (str[i] - '0');
}
return temp % MOD;
}
ll ta = cal_num(str, st, min_pos, a);
ll tb = cal_num(str, min_pos + 1, ed, a);
switch (str[min_pos]) {
case '+' :
return (ta + tb) % MOD;
case '-' :
return (ta - tb + MOD) % MOD;
case '*' :
return (ta * tb) % MOD;
case '^' :
return quick_pow(ta, tb);
}
return 0;
}
#define MAX_RANGE 5
int main() {
// char s[100] = "((1+2)*3) ^ a";
// printf("%d\n", cal_num(s, 0, strlen(s), 2));
int rand_num[5] = {1, 2, 3, 4, 5};
int n;
char st[100], ed[100][100];
while (scanf("%[^\n]s", st) != EOF) {
scanf("%d", &n);
for (int i = 0 ; i < n ; ++i) {
getchar();
scanf("%[^\n]s", ed[i]);
}
int vis[30] = {0}; // vis[i] = 0代表成功通过测试
for (int i = 0 ; i < MAX_RANGE ; ++i) {
int std_value = cal_num(st, 0, strlen(st), rand_num[i]);
for (int j = 0 ; j < n ; ++j) {
if (vis[j]) continue;
int temp_value = cal_num(ed[j], 0, strlen(ed[j]), rand_num[i]);
if (temp_value != std_value) {
vis[j] = 1;
}
}
}
for (int i = 0 ; i < n ; ++i) {
if (vis[i]) continue;
printf("%c", i + 'A');
}
printf("\n");
getchar();
}
return 0;
}
如要转载请注明转载出处:http://www.cnblogs.com/WArobot