重返小学计算表达式基础—牛客

题意

题目链接: https://ac.nowcoder.com/acm/contest/19859/V
 计算表达式仅有,0-9、+、-、*、/、^、!字符组成(表达式均合法),优先级! > ^ > *,/ > +, -
 一切数值计算均受限于模65536的数域,即每一步运算都要对65536取模


输入输出描述
 输入:输入n,表示n个测试用例,随后紧跟着n行表达式。
 输出:每行输出对应案例表达式运算的结果,如遇到除以0的算数错误,请输出ArithmeticException。


Sample Input

2
2!!
3/2^4^4

Sample Output

2
ArithmeticException


#解析 :
 解析&&细节,见以下注释


AC代码 - - -

#solution1

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod = 65536,p[65536];
int len,i;
char a[100+5];
inline int ini(){
    int x=0,f=1;
    char c=getchar();
    while(c<48||c>57){
        if(c==-1) return -1;
        c=getchar();
    }
    while(c>=48&&c<=57){
        x=(x<<3)+(x<<1)+(c^48);
        c=getchar();
    }
    return x*f;
}
inline void ins() {
    len = i = 0;
    char c = getchar();
    while(!(c>=48&&c<=57||c=='-'||c=='+'||c=='/'||c=='*'||c=='^'||c=='!')) c=getchar();
    while(c>=48&&c<=57||c=='-'||c=='+'||c=='/'||c=='*'||c=='^'||c=='!') {
        a[len++] = c;
        c = getchar();
    }
    
}
ll getsnum() {
    ll x = 0;
    while(i<len&&a[i]>=48&&a[i]<=57) {
        x = (x<<3)+(x<<1)+(a[i]^48);
        x %= mod;
        ++i;
    }
    return x;
}
ll kp(ll b,ll k) {
    ll res = 1;
    while(k) {
        if(k%2==1) {
            res = res*b%mod;
        }
        b = b*b%mod;
        k /= 2;
    }
    return res;
}
int main() {
    int T = ini();
    p[0]=1;
    for(int j = 1; j < mod; ++j) p[j] = p[j-1]*j%mod;
    if(T<0) return 0;
    while(T--) {
        ins();
        ll res = 0, f = 1, pre = 0, ch = 0;
        bool flag = true, anwserf = true;
        while(i<len) {
            if(a[i]=='-') f = -1;
            if(a[i]=='-'||a[i]=='+') ++i;
            while(i<len&&a[i]!='-'&&a[i]!='+') {//I.以加好为分割点
                if(!(a[i]>=48&&a[i]<=57)) ch = a[i++];//II.以*或/为分割点
                ll ans = getsnum();
                while(i<len&&a[i]=='!') {//难点1,阶乘后面有^,例4!!!^2^2
                     ans = p[ans];
                    ++i;
                }
                while(i<len&&a[i]=='^') {//III.以^作为分割点,根据最高优先级,我们可以把类似n!看成一个整体
                    ++i;
                    ll x1 = getsnum();
                    while(i<len&&a[i]=='!') {//难点2,^后面的数字n!,例3!!^7!^3^4!!^7
                        x1 = p[x1];//难点3,阶乘需要打表即可,一个最多只有mod个,一个一个求会超时
                        ++i;
                    }
                    ans = kp(ans,x1);
                }
                if(flag) {
                    pre=ans;
                    flag = false;
                }else {
                    if(ch=='*') {
                        pre = pre*ans%mod;
                    }else {
                        if(ans==0) {
                            i=len;
                            anwserf = false;
                            break;
                        }else {
                            pre /= ans;
                        }
                    }
                }
            }
            res = (res+f*pre)%mod;
            pre = 0;
            f = 1;
            flag = true;
        }
        if(anwserf) printf("%lld\n",res);
        else printf("ArithmeticException\n");
    }
    return 0;
}




  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值