147 lines
3.6 KiB
C++
147 lines
3.6 KiB
C++
#include <bits/stdc++.h>
|
|
using namespace std;
|
|
|
|
struct Node {
|
|
char sign; // 运算符,叶子节点为 '?'
|
|
long long num; // 数字
|
|
Node* left;
|
|
Node* right;
|
|
|
|
Node(): sign('?'), num(-1), left(nullptr), right(nullptr) {}
|
|
Node(char s): sign(s), num(-1), left(nullptr), right(nullptr) {}
|
|
Node(long long n): sign('?'), num(n), left(nullptr), right(nullptr) {}
|
|
};
|
|
|
|
// 快速幂,整数
|
|
long long fastpow(long long base, long long exp){
|
|
long long res = 1;
|
|
while(exp > 0){
|
|
if(exp & 1) res *= base;
|
|
base *= base;
|
|
exp >>= 1;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
// 运算优先级
|
|
int level(char c){
|
|
switch(c){
|
|
case '+': case '-': return 1;
|
|
case '*': case '/': return 2;
|
|
case '^': return 3;
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
// 找到最外层优先级最低的运算符
|
|
int findexp(const string &s, int l, int r){
|
|
int pos = -1;
|
|
int minLevel = 114514;
|
|
int balance = 0; // 括号深度
|
|
for(int i = r; i >= l; --i){ // 右结合,优先找右边
|
|
if(s[i] == ')') balance++;
|
|
else if(s[i] == '(') balance--;
|
|
else if(balance == 0 && level(s[i]) > 0){
|
|
if(level(s[i]) <= minLevel){
|
|
minLevel = level(s[i]);
|
|
pos = i;
|
|
}
|
|
}
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
// 字符串转整数
|
|
long long toNum(const string &s, int l, int r){
|
|
long long tmp = 0;
|
|
while(l <= r && isspace((unsigned char)s[l])) l++;
|
|
while(r >= l && isspace((unsigned char)s[r])) r--;
|
|
if(l > r) return 0;
|
|
for(int i = l; i <= r; ++i){
|
|
if(!isdigit(s[i])) return 0;
|
|
tmp = tmp * 10 + (s[i] - '0');
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
class Expression {
|
|
public:
|
|
string exp;
|
|
Node* root;
|
|
long long result;
|
|
bool isValid;
|
|
|
|
Expression(const string &s): exp(s), root(nullptr), result(0), isValid(true) {}
|
|
|
|
Node* build(const string &s, int l, int r){
|
|
while(l <= r && s[l] == ' ') l++;
|
|
while(l <= r && s[r] == ' ') r--;
|
|
if(l > r) return nullptr;
|
|
|
|
// 外层括号处理
|
|
if(s[l] == '(' && s[r] == ')'){
|
|
int balance = 0;
|
|
bool hasOuter = true;
|
|
for(int i = l; i <= r; ++i){
|
|
if(s[i] == '(') balance++;
|
|
else if(s[i] == ')') balance--;
|
|
if(balance == 0 && i < r){
|
|
hasOuter = false;
|
|
break;
|
|
}
|
|
}
|
|
if(hasOuter) return build(s, l+1, r-1);
|
|
}
|
|
|
|
int pos = findexp(s, l, r);
|
|
if(pos == -1){
|
|
long long val = toNum(s, l, r);
|
|
return new Node(val);
|
|
}
|
|
|
|
Node* tmp = new Node(s[pos]);
|
|
tmp->left = build(s, l, pos-1);
|
|
tmp->right = build(s, pos+1, r);
|
|
return tmp;
|
|
}
|
|
|
|
long long calc(Node* r, bool &v){
|
|
if(!r) return 0;
|
|
if(r->sign == '?') return r->num;
|
|
|
|
long long left = calc(r->left, v);
|
|
long long right = calc(r->right, v);
|
|
|
|
switch(r->sign){
|
|
case '+': return left + right;
|
|
case '-': return left - right;
|
|
case '*': return left * right;
|
|
case '/':
|
|
if(right == 0){ v = false; return 0; }
|
|
return left / right;
|
|
case '^':
|
|
if(right < 0){ v = false; return 0; }
|
|
return fastpow(left, right);
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
void calc(){
|
|
isValid = true;
|
|
result = calc(root, isValid);
|
|
}
|
|
};
|
|
|
|
int main(){
|
|
string s;
|
|
while(getline(cin, s)){
|
|
Expression tree(s);
|
|
tree.root = tree.build(s, 0, s.length()-1);
|
|
tree.calc();
|
|
if(tree.isValid) cout << tree.result << endl;
|
|
else cout << "INVALID" << endl;
|
|
}
|
|
return 0;
|
|
}
|
|
|