You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
2.3 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 100010, mod = 10007;
/*
stack<vector<int>> num;
a[0],a[1],01
101
num.push({1, 1});
*/
stack<char> op; // 运算符栈
stack<vector<int>> num; // 得0的方案数num[0],得1的方案数num[1]
// 运算符优化级
unordered_map<char, int> h = {{'+', 1}, {'*', 2}};
void eval() {
// 运算符
auto c = op.top();
op.pop();
// 两个数本题的弹出顺序不重要事实上是先b后a,因为是栈
auto b = num.top();
num.pop();
auto a = num.top();
num.pop();
// ⊕ 运算符
if (c == '+')
num.push({a[0] * b[0] % mod,
(a[0] * b[1] + a[1] * b[0] + a[1] * b[1]) % mod});
else // × 运算符
num.push({(a[0] * b[0] + a[1] * b[0] + a[0] * b[1]) % mod,
a[1] * b[1] % mod});
}
int main() {
int n;
string expr;
cin >> n >> expr;
// 第一个位置,需要放上一个数字可以是0也可以是1方案数都是1
num.push({1, 1});
for (auto c : expr) { // 读入表达式
if (c == '(')
op.push(c); // 左括号入栈
else if (c == '+' || c == '*') {
// 通过while循环把栈内的表达式先计算出结果,再将当前操作符入栈
while (op.size() && h[op.top()] >= h[c]) eval();
op.push(c);
// 处理完操作符需要模拟下面的数字是0还是1
num.push({1, 1}); // 无论是0还是1方案数都是1,这样所有情况都考虑到了
} else { // 右括号
while (op.top() != '(') eval();
op.pop();
}
}
// 1*1-0 类似这样的表达式op栈中应该有*-两种符号,需要再次弹栈计算
while (op.size()) eval();
cout << num.top()[0] << endl;
return 0;
}