**鏈接 : ** 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;
}