NC16539 [NOIP2013]表达式求值
题目
题目描述
给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。
输入描述
输入仅有一行,为需要你计算的表达式,表达式中只包含数字、加法运算符“+”和乘法运算符“*”,且没有括号。
所有参与运算的数字均为 到 之间的整数。
输入数据保证这一行只有 ~ 、+ 、*这12种字符。
输出描述
输出只有一行,包含一个整数,表示这个表达式的值。注意:当答案长度多于 位时,请只输出最后 位,前导 不输出。
示例1
输入
1+1*3+4
输出
8
说明
计算的结果为 ,直接输出 。
示例2
输入
1+1234567890*1
输出
7891
说明
计算的结果为 ,输出后 位,即 。
示例3
输入
1+1000000003*1
输出
4
说明
计算的结果为 ,输出后 位,即 。
备注
对于 的数据, ≤表达式中加法运算符和乘法运算符的总数≤ ;
对于 的数据, ≤表达式中加法运算符和乘法运算符的总数≤ ;
对于 的数据, ≤表达式中加法运算符和乘法运算符的总数≤ 。
题解
方法一
知识点:分治。
表达式的运算有优先级直接读取难以计算,但运算总有最后一步,通过找到最后一次的运算将表达式以这个符号拆成左右两部分,就可以展开递归进行相同的操作。每次只需要遍历一遍当前表达式,找到所有符号最后出现的位置,加号优先判断,如果加号没有位置那就看乘号,来决定下一次拆分,如果都没有的话那说明是个纯数字,就字符串转换数字即可。注意到结果保留末四位,等价于模 ,因为加法乘法在模意义下也具有意义。
此解法属于万能解法,可以十分方便处理所有运算符的一系列计算(包括但不限于加,减,乘,除,乘方,阶乘),而且可以通过改进变为可以带括号。平均复杂度 ,但如果每次拆分都在最左最右,那么会退化到 ,而本题有连续加的特殊数据因此在加法处判断后立即break可以优化。但如果是乘法则无法直接break优化,因为无法确定后方是否有更小优先级的运算符,但本题没有连续乘法的数据qwq。
时间复杂度 平均: 最差:
空间复杂度
方法二
知识点:模拟。
发现连续乘法的数字可以连续算出放入临时变量,然后加入最终答案,因为只有加法和乘法。
时间复杂度
空间复杂度
代码
方法一
#include <bits/stdc++.h> using namespace std; const int mod = 1e4; string s; int StoI(int l, int r) { int ans = 0; for (int i = l;i <= r;i++) ans = (10 * ans + s[i] - '0') % mod; return ans; } int calc(int l, int r) { int pos[2] = { -1,-1 };///+,* for (int i = l;i <= r;i++) {///找到最后一次出现的符号(因为没有括号直接找最后一次的) if (s[i] == '+') { pos[0] = i; break; }///找到+可以直接退出,避免最差复杂度 else if (s[i] == '*') pos[1] = i; } if (!~pos[0] && !~pos[1]) return StoI(l, r);///纯数 else if (~pos[0]) return (calc(l, pos[0] - 1) + calc(pos[0] + 1, r)) % mod; else if (~pos[1]) return calc(l, pos[1] - 1) * calc(pos[1] + 1, r) % mod; return 0;///过编译 } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> s; cout << calc(0, s.length() - 1) << '\n'; return 0; }
方法二
#include <bits/stdc++.h> using namespace std; const int mod = 1e4; int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); string s; cin >> s; s += '+';///终止最后一段 int ans = 0; for (int i = 0, tmp = 0, last = 1;i < s.length();i++) {///tmp指一个数字,last指一个乘法数块 if ('0' <= s[i] && s[i] <= '9') tmp = (tmp * 10 + s[i] - '0') % mod;///更新tmp else if (s[i] == '+') {///把tmp乘进last,更新ans、tmp、last last = last * tmp % mod; ans = (ans + last) % mod; tmp = 0; last = 1; } else if (s[i] == '*') {///把tmp乘进last,更新tmp last = last * tmp % mod; tmp = 0; } } cout << ans << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16404613.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧