NC21181 重返小学
题目
题目描述
时光依旧,岁月匆匆。转眼间,曾经的少年郭嘉烜已经长大成人,考上了一所优秀的大学——兰州大学。在经历了一年来自牛顿、莱布尼茨、拉普拉斯的精神洗礼后,他终于决定回到小学,重新回到加减乘除的怀抱中。
输入描述
第一行,一个整数 ,表示案例的个数。
接下来的T行,每行一个字符串(长度小于等于 ),字符串仅由0-9、+、-、*、/、^、!字符组成,数字表示一个数值,范围为 ,且数字不存在前导零,其他符号表示一种运算规则,规则的描述如下:
+:数字1 +数字2 =两个数字之和,+号的优先级为1
-:数字1 -数字2 =两个数字之差,-号的优先级为1
*:数字1 * 数字2 =两个数字之积,* 号的优先级为2
/:数字1 /数字2 =两个数字之商(舍去小数),/号的优先级为2
^:数字1 ^数字2 =数字1的数字2次方,^号的优先级为3
!:数字1 ! =数字1的阶乘,!号的优先级为4
按照优先级从高到低的顺序依次计算,同级运算时,从左到右依次计算。
输入保证对于每个字符串,满足上述条件,一行输入,以换行符结束。保证式子的表达式语义正确。特别的,一切数值计算均受限于模 的数域,即每一步运算都要对 取模,取模的规则同C语言规范。同时,任意数的 次方等于 。
输出描述
T行,T个整数。
每行输出对应案例表达式运算的结果,如遇到除以0的算数错误,请输出ArithmeticException。
示例1
输入
1 4*3/2^0+9
输出
21
说明
优先计算2!=2,之后以前一步的结果继续计算2!=2遇到换行符结束运算并输出
示例2
输入
2 2!! 3/2^4^4
输出
2 ArithmeticException
说明
优先计算 2 ^ 4 ^ 4 ,由于其结果对 取模为 ,因此下一步运算变成 从而产生ArithmeticException
备注
建议使用C/C++解答本题。
题解
知识点:分治。
按优先级给符号分类,记录每类符号最后一个出现的地方位置,随后找到优先级最低且符号位置存在的位置划分表达式为左右两边,对他们进行相同的操作,然后根据返回表达式值以及对应符号处理得到结果再返回到上一层。
在这里我们没有处理负号,看似无法划分左右,但实际上还是可以的。比如, 可以划分成空区间(左右端点越界)以及 ,前者由于符号位置都不存在直接进入 函数,由于左右端点越界直接返回 ;后者会被转换成 ,最后就是 成立。
乘方用快速幂,关于除法非法可以设置全局变量 检验。
注意这道题阶乘打表不然超时,注意乘法可能过程越界。
时间复杂度 平均: 最差:
空间复杂度
代码
#include <bits/stdc++.h> #define ll long long using namespace std; const int mod = 65536; int f[mod + 7]; string s; bool flag; void fact(int n) { f[0] = 1; for (int i = 1;i <= n;i++) f[i] = f[i - 1] * i % mod; } int StoI(int l, int r) { int ans = 0; for (int i = l;i <= r;i++) ans = (ans * 10 + s[i] - '0') % mod; return ans; } int qpow(int a, int k) { int ans = 1; while (k) { if (k & 1) ans = 1LL * ans * a % mod; k >>= 1; a = 1LL * a * a % mod; } return ans; } int calc(int l, int r) { int pos[4] = { -1,-1,-1,-1 };///+-,*/,^,! for (int i = l;i <= r;i++) {///最后运算符号判断(无括号) if (s[i] == '+' || s[i] == '-') pos[0] = i; else if (s[i] == '*' || s[i] == '/') pos[1] = i; else if (s[i] == '^') pos[2] = i; else if (s[i] == '!') pos[3] = i; } if (!~pos[0] && !~pos[1] && !~pos[2] && !~pos[3]) return StoI(l, r);///纯数判断(无括号) else if (~pos[0]) { if (s[pos[0]] == '+') return (calc(l, pos[0] - 1) + calc(pos[0] + 1, r)) % mod; else if (s[pos[0]] == '-') return (calc(l, pos[0] - 1) - calc(pos[0] + 1, r) + mod) % mod; } else if (~pos[1]) { int lans = calc(l, pos[1] - 1); int rans = calc(pos[1] + 1, r); if (s[pos[1]] == '*') return 1LL * lans * rans % mod; else if (s[pos[1]] == '/') { if (rans) return lans / rans; else flag = 0; } } else if (~pos[2]) { if (s[pos[2]] == '^') return qpow(calc(l, pos[2] - 1), calc(pos[2] + 1, r)); } else if (~pos[3]) { if (s[pos[3]] == '!') return f[calc(l, pos[3] - 1)]; } return 0;///过编译 } bool solve() { flag = 1; cin >> s; int ans = calc(0, s.length() - 1); if (flag) cout << ans << '\n'; else return false; return true; } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); fact(mod - 1); int t = 1; cin >> t; while (t--) { if (!solve()) cout << "ArithmeticException" << '\n'; } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16404948.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧