传送门:牛客
题目描述:
题目描述
给出一个表达式,其中运算符仅包含+,-,*,/,^(加 减 乘 整除 乘方)要求求出表达式的最终值
数据可能会出现括号情况,还有可能出现多余括号情况
数据保证不会出现\geq 2^{31}的答案数据保证不会出现≥2^31的答案
数据可能会出现负数情况
输入:
(2+2)^(1+1)
输出:
16
首先这道题是这些题的进一步进阶题面,在之前题目的基础上又加上了括号的条件.建议先去熟练掌握上述题目在了解此题
主要思路:
观察这道题讲了可能出现多括号的情况,显然这种情况是不符合正常表达式的,因此我们需要先解决这种不正常情况,下面是我的解决方案:
观察多余括号的具体情形(()()
我们为了方便起见,设左括号的数量为left,右括号数量为right,我们从左往右去枚举,发现如果一旦left<right的话即代表是多余括号的,因为此时此刻right比left多了,但是left是不会再增加的 同理,我们还需要处理左括号多余的情况,这个时候我们只要从右往左枚举一遍即可.
具体到代码实现,下面代码我a数组
代表刚开始输入的表达式字符串,并在输入的同时直接处理右括号多余的情况(即保证left>=right)
并且再来一次循环枚举(因为此处为了处理方便,我没有用string,用了char,导致我少了一些string的方法),此时处理左括号多余的情况
然后注意此刻我们是倒着循环赋值的,因此我们需要翻转字符数组,得到aa数组
下面是代码(我还增加了对阶乘的处理)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <string.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
ll x=0,w=1;char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*w;
}
#define maxn 1000000
const int mod=65536;
int f[mod];
//这是快速幂的代码,用处和pow函数差不多,但是更快,可以学一下
ll power(ll x,ll y){
if(y==0)return 1;
ll sum=1;
while(y){
if(y&1){
sum=sum*x;
}
x=x*x;
y=y>>1;
}
return sum;
}
char a[10000];
char aa[10000];
char aaa[10000];
ll toNum(ll l,ll r) {
ll sum=0;
for(int i=l;i<=r;i++) {
sum=sum*10+aa[i]-'0';
}
return sum;
}
ll flag=0;
ll calc(ll l,ll r) {
if(l>r) return 0;
ll pos1=-1,pos2=-1,pos3=-1,pos4=-1;
ll cnt=0;
/*注意这里对括号左右个数的理解,只有当一个区域内的左右括号的数量一致时
此时我们的区域才是一个完整的表达式区域,比如((a*2)+7)表达式,如果没有对左右括
号数量的判断的话,遇到+就会直接直接开始分治了,此时左边是((a*2),右边是7),显
然是不对的.
*/
for(int i=l;i<=r;i++) {
if(aa[i]=='(') cnt++;
if(aa[i]==')') cnt--;
if((aa[i]=='+'||aa[i]=='-')&&cnt==0) pos1=i;
else if((aa[i]=='*'||a[i]=='/')&&cnt==0) pos2=i;
else if(aa[i]=='^'&&cnt==0) pos3=i;
else if(aa[i]=='!'&&cnt==0) pos4=i;
}
if(pos1==-1&&pos2==-1&&pos3==-1&&pos4==-1) {
/*当我们一个区域什么符号都没有时(注意此时的没有任何符号是在左右括号数量
一样的情况下),得到的要不是一个普通的数字,要不就是类似于(1+7)这种的带括号的
表达式,那么此时要求表达式的值我们肯定是不用带括号的,所以递归求解l+1,r-1即可*/
if(aa[l]=='('&&aa[r]==')') {
return calc(l+1,r-1);
}
else return toNum(l,r);
}
else if(pos1!=-1) {
if(aa[pos1]=='+') return (calc(l,pos1-1)+calc(pos1+1,r));
else return (calc(l,pos1-1)-calc(pos1+1,r));
}
else if(pos2!=-1) {
if(aa[pos2]=='*') return (calc(l,pos2-1)*calc(pos2+1,r));
else {
if(calc(pos2+1,r)==0) flag=1;
else return (calc(l,pos2-1)/calc(pos2+1,r));
}
}
else if(pos3!=-1) {
return power(calc(l,pos3-1),calc(pos3+1,r));
}
else if(pos4!=-1) {
int aaaa=calc(l,pos4-1);
return f[aaaa];
}
return 0;
}
ll lt=0,rt=0;
int main() {
f[0]=1;
for(int i=1;i<mod;i++) f[i]=f[i-1]*i%mod;
ll lens=0;
while((a[lens]=getchar())!=EOF) {
if(a[lens]=='(') {
lt++;
}else if(a[lens]==')') {
rt++;
if(rt>lt) {
lens--;
rt--;
}
}
lens++;
}
int lens2=0;
lt=0,rt=0;
for(int i=lens-2;i>=0;i--) {
if(a[i]==')') rt++;
if(a[i]=='(') {
lt++;
if(lt>rt) {
lt--;
continue;
}
}
aaa[lens2++]=a[i];
}
for(int i=0;i<lens2;i++){
aa[i]=aaa[lens2-i-1];
}
flag=0;
ll ans=calc(0,strlen(aa)-1);
if(flag==0) cout<<ans<<endl;
else cout<<"ArithmeticException"<<endl;
return 0;
}