計蒜客 表達式 (遞歸)


**鏈接 : ** 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章