This commit is contained in:
e2hang
2025-10-24 09:52:24 +08:00
parent 5e189f9bb2
commit 218a2fb56a
8 changed files with 1011 additions and 0 deletions

View File

@@ -0,0 +1,146 @@
#include <bits/stdc++.h>
using namespace std;
struct Node {
char sign; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҷ<EFBFBD>ӽڵ<D3BD>Ϊ '?'
long long num; // <20><><EFBFBD><EFBFBD>
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) {}
};
// <20><><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD>
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;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>
int level(char c){
switch(c){
case '+': case '-': return 1;
case '*': case '/': return 2;
case '^': return 3;
default: return 0;
}
}
// <20>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int findexp(const string &s, int l, int r){
int pos = -1;
int minLevel = 114514;
int balance = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for(int i = r; i >= l; --i){ // <20>ҽ<EFBFBD><D2BD>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ұ<EFBFBD>
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;
}
// <20>ַ<EFBFBD><D6B7><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŵ<EFBFBD><C5B4><EFBFBD>
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;
}