【题目链接】

ybt 1962:【13NOIP普及组】表达式求值
洛谷 P1981 [NOIP2013 普及组] 表达式求值

【题目考点】

  1. 中缀表达式转后缀表达式,后缀表达式求值
  2. 中缀表达式求值

【解题思路】

表达式中只有加法和乘法,数字是0∼231−10 \sim 2^{31}-10∼231−1,运算中不会出现负数。由于最后只需要最后4位,即结果%10000的值。根据同余定理:
(a+b)%m=(a%m+b%m)%m(a+b)\%m = (a\%m+b\%m)\%m(a+b)%m=(a%m+b%m)%m,(a∗b)%m=((a%m)∗(b%m))%m(a*b)\%m = ((a\%m)*(b\%m))\%m(a∗b)%m=((a%m)∗(b%m))%m。
运算时,将每个数字都%10000,每次计算后的结果都%10000,最终得到的结果就是真实结果%10000后的值。
具体解法有两种

  1. 先将中缀表达式转为后缀表达式,而后求后缀表达式的值
  2. 直接求中缀表达式的值

【题解代码】

解法1:先将中缀表达式转为后缀表达式,而后求后缀表达式的值

中缀表达式转后缀表达式方法:

  1. 从左向右扫描表达式字符串。
  2. 遇到数字时,直接输出。
  3. 遇到运算符时,如果栈空,或该运算符优先级大于栈顶运算符优先级,则入栈。否则运算符出栈并输出。重复这一过程。
  4. 扫描结束后若栈中有运算符,都出栈并输出。

后缀表达式求值:

  1. 从左向右扫描字符串
  2. 遇到数字时,将数字入栈。
  3. 遇到运算符时,弹出栈顶的两个数,用该运算符对它们做相应的计算,结果入栈。
  4. 扫描结束后,栈顶数字就是结果。

本题解中,用一个数组e表示后缀表达式,数组中元素e[i]若大于等于0,表示数字。若e[i]为-1,表示乘号,若e[i]为-2,表示加号。这里乘号的值大于加号的值,可以表示乘号的优先级大于加号。

运算符最多10510^5105个,那么运算符与数字加起来不会超过3∗1053*10^53∗105个,所以数组大小开为3∗1053*10^53∗105。

#include <bits/stdc++.h>
using namespace std;
#define N 100000
#define M 10000
#define ADD -2 //加号
#define MULT -1//乘号
int e[3*N], e_i;//保存后缀表达式,e[i]若大于等于0,表示数字。若e[i]为-1,表示乘号,若e[i]为-2,表示加号。e_i:e数组待添加元素的位置
int stk[2*N], top;
int main()
{char c;int num = 0, cVal, a, b;//cVal:运算符的值:加号为-2,乘号为-1; a,b:运算数c = getchar();//输入并构建后缀表达式while(c != EOF && c != '\n')//不确定OJ输入的末尾是文件末尾EOF,还是换行符'\n',所以二者都可能是输入的结束符号,都判断一下。{if(c >= '0' && c <= '9')//c是数字num = (num * 10 + c - '0') % M;else//c是运算符{e[e_i++] = num;//后缀表达式添加numnum = 0;if(c == '+')cVal = ADD;//如果是加号elsecVal = MULT;//如果是乘号while(!(top == 0 || cVal > stk[top]))//如果栈中有运算符,且运算符c比栈顶运算符的优先级相等或更低,则运算符出栈,输出到后缀表达式e[e_i++] = stk[top--];stk[++top] = cVal;//此时运算符入栈}c = getchar();}e[e_i++] = num;//添加最后一个数字while(top > 0)//将栈中剩余的运算符加入后缀表达式e[e_i++] = stk[top--];//此时后缀表达式构建完成,开始根据后缀表达式求值for(int i = 0; i < e_i; ++i){if(e[i] >= 0)//如果是数字stk[++top] = e[i];//数字入栈else//如果是运算符{a = stk[top--];//数字出栈b = stk[top--];//数字出栈if(e[i] == ADD)//如果是加号stk[++top] = (a + b) % M;//计算结果入栈else//如果是乘号stk[++top] = (a * b) % M;//计算结果入栈}}cout<<stk[top];//栈顶数值即为运算结果return 0;
}

解法2:直接求中缀表达式的值

中缀表达式求值:

  1. 设数字栈,运算符栈。从左向右扫描表达式
  2. 遇到数字进数字栈
  3. 遇到运算符,如果运算符栈栈空,或该运算符优先级大于栈顶运算符优先级,则入栈。否则运算符出栈,从数字栈出栈2个数字,进行计算,结果在数字栈入栈。重复这一过程。
  4. 扫描结束后,运算符栈出栈运算符,进行运算,直到运算符栈为空。最后数字栈栈顶的数字,就是结果。
#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define M 10000
int nStk[N], nTop, cTop;//nStk:数字栈 nTop:数字栈栈顶位置 cTop:运算符栈栈顶位置
char cStk[N];//cStk:运算符栈
int main()
{char c, tc;//c:读入的字符 tc:出栈的字符int num = 0, a, b;c = getchar();while(c != EOF && c != '\n'){if(c >= '0' && c <= '9')//如果遇到数字字符num = (num * 10 + c - '0') % M;else//如果遇到运算符{nStk[++nTop] = num;num = 0;while(!(cTop == 0 || c == '*' && cStk[cTop] == '+'))//栈空或要入栈的运算符比栈顶运算符优先级高,才可以入栈,其他情况都出栈,做运算。{a = nStk[nTop--];//数字栈出栈两个数b = nStk[nTop--];tc = cStk[cTop--];//运算符栈出栈一个运算符,if(tc == '*')//进行计算,结果存入数字栈nStk[++nTop] = (a * b) % M;elsenStk[++nTop] = (a + b) % M;}cStk[++cTop] = c;}c = getchar();}nStk[++nTop] = num;//添加最后一个数字while(cTop > 0)//如果运算符栈还有运算符,运算符出栈,运算,直到栈空为止{a = nStk[nTop--];//数字栈出栈两个数b = nStk[nTop--];tc = cStk[cTop--];//运算符栈出栈一个运算符,if(tc == '*')//进行计算,结果存入数字栈nStk[++nTop] = (a * b) % M;elsenStk[++nTop] = (a + b) % M;}cout<<nStk[nTop];//数字栈栈顶即为结果return 0;
}

同样解法,使用string读入,使用c++ stl的stack类来做

#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define M 10000
stack<int> nStk;//nStk:数字栈
stack<char> cStk;//cStk:运算符栈
string s;
int main()
{char c;int num = 0, a, b;cin>>s;for(int i = 0; i < s.length(); ++i){if(s[i] >= '0' && s[i] <= '9')num = (num * 10 + s[i] - '0') % M;else{nStk.push(num);num = 0;while(!(cStk.empty() || s[i] ==    '*' && cStk.top() == '+')){b = nStk.top(); nStk.pop();a = nStk.top(); nStk.pop();c = cStk.top(); cStk.pop();if(c == '*')nStk.push(a * b % M);elsenStk.push((a + b) % M);}cStk.push(s[i]);}}nStk.push(num);//最后的数字入栈 while(cStk.empty() == false)//其余运算符出栈,运算 {b = nStk.top(); nStk.pop();a = nStk.top(); nStk.pop();c = cStk.top(); cStk.pop();if(c == '*')nStk.push(a * b % M);elsenStk.push((a + b) % M);}cout<<nStk.top();fclose(stdin);return 0;
}

信息学奥赛一本通 1962:【13NOIP普及组】表达式求值 | 洛谷 P1981 [NOIP2013 普及组] 表达式求值相关推荐

  1. 信息学奥赛一本通 1961:【13NOIP普及组】计数问题 | 洛谷 P1980 [NOIP2013 普及组] 计数问题

    [题目链接] ybt 1961:[13NOIP普及组]计数问题 洛谷 P1980 [NOIP2013 普及组] 计数问题 [题目考点] 1. 数字拆分 [解题思路] 遍历1~n的各个数字,对每个数字做 ...

  2. 信息学奥赛一本通 1956:【11NOIP普及组】表达式的值 | 洛谷 P1310 [NOIP2011 普及组] 表达式的值

    [题目链接] ybt 1956:[11NOIP普及组]表达式的值 洛谷 P1310 [NOIP2011 普及组] 表达式的值 [题目考点] 表达式树 由带括号的中缀表达式构建表达式树 [解题思路] 思 ...

  3. 信息学奥赛一本通 1415:【17NOIP普及组】图书管理员 | 洛谷 P3955 [NOIP2017 普及组] 图书管理员

    [题目链接] ybt 1415:[17NOIP普及组]图书管理员 洛谷 P3955 [NOIP2017 普及组] 图书管理员 [题目考点] 1. 枚举 2. 二分 [解题思路] 解法1:枚举 对于每个 ...

  4. 信息学奥赛一本通 1314:【例3.6】过河卒(Noip2002) | 1921:【02NOIP普及组】过河卒 | 洛谷 P1002 [NOIP2002 普及组] 过河卒

    [题目链接] ybt 1314:[例3.6]过河卒(Noip2002) ybt 1921:[02NOIP普及组]过河卒 洛谷 P1002 [NOIP2002 普及组] 过河卒 [题目考点] 1. 坐标 ...

  5. 信息学奥赛一本通 1967:【14NOIP普及组】螺旋矩阵 | 洛谷 P2239 [NOIP2014 普及组] 螺旋矩阵

    [题目链接] ybt 1967:[14NOIP普及组]螺旋矩阵 洛谷 P2239 [NOIP2014 普及组] 螺旋矩阵 类似考题: 洛谷 P1014 [NOIP1999 普及组] Cantor 表 ...

  6. 信息学奥赛一本通 1919:【02NOIP普及组】选数 | 洛谷 P1036 [NOIP2002 普及组] 选数

    [题目链接] ybt 1919:[02NOIP普及组]选数 洛谷 P1036 [NOIP2002 普及组] 选数 [题目考点] 1.排列组合 2.深搜(子集树) 3.质数 [解题思路] 深搜(子集树) ...

  7. 信息学奥赛一本通 1978:【18NOIP普及组】标题统计 | 洛谷 P5015 [NOIP2018 普及组] 标题统计

    [题目链接] ybt 1978:[18NOIP普及组]标题统计 洛谷 P5015 [NOIP2018 普及组] 标题统计 [题目考点] 1. 字符串 读入带空格的字符串 将带空格的字符串读入字符数组 ...

  8. 信息学奥赛一本通 1365:FBI树(fbi) | 1928:【04NOIP普及组】FBI树 | 洛谷 P1087 [NOIP2004 普及组] FBI 树

    [题目链接] ybt 1365:FBI树(fbi) ybt 1928:[04NOIP普及组]FBI树 洛谷 P1087 [NOIP2004 普及组] FBI 树 [题目考点] 1. 二叉树 [解题思路 ...

  9. 信息学奥赛一本通 1890:【15NOIP提高组】跳石头 | 洛谷 P2678 [NOIP2015 提高组] 跳石头

    [题目链接] ybt 1890:[15NOIP提高组]跳石头 洛谷 P2678 [NOIP2015 提高组] 跳石头 ybt 1247:河中跳房子 OpenJudge NOI 1.11 10:河中跳房 ...

最新文章

  1. 不一样的Office 365之 —— Mini Hybrid了解一下(三)迁移邮箱
  2. 树莓派 -- 按键 (key)使用BCM2835 gpio library
  3. asp接收ajax乱码_Asp中处理AJAX乱码问题总结
  4. 双网卡oracle rac,Linux+Oracle 10g RAC双网卡绑定和解除绑定的实现(2)
  5. Exception in thread main java.lang.NoClassDefFoundError
  6. 设计模式-缺省适配类.
  7. 当代刻板程序员生态图鉴!网友:哈哈哈太真实了
  8. gui卡顿 python_视频下载神器(youget),在 Python 中怎么使用?
  9. 包打包和解析过程 unity_Unity AssetBundle 解析 (一)AB包介绍与构建
  10. Pandas官方文档(中文版)Pdf
  11. matConvNet学习-使用GPU
  12. 解决在ajax回调函数中循环遍历data数组无法获取数组下标为0之后的重复数据的问题
  13. android 图片3d,Android实现3D图片浏览效果示例
  14. 使用Python和Numpy构建神经网络模型
  15. 单片机教学打铃控制器C语言
  16. 018 The Scala Programming Language
  17. po是什么意思java_在Java中VO , PO , BO , QO, DAO ,POJO是什么意思
  18. IOS-layoutSubviews方法的调用时机
  19. 聊天机器人的产品打造和商业变现(根据辣妈帮-王安静博士-演讲整理)
  20. express-ws实现客服聊天功能

热门文章

  1. C/C++开发工具大比拼【转】
  2. 不学Python的同学,“跳一跳”都输了
  3. STM32之ADC单通道单次例程
  4. 面试官:Java为什么只有值传递?
  5. 作为一个程序员,CPU的这些硬核知识你必须会!
  6. 架构专家高磊:缓存为王——无线缓存架构优化
  7. Java 解析 XML
  8. Linux程序分析工具介绍—ldd,nm
  9. MySQL学习笔记_6_SQL语言的设计与编写(下)
  10. MSsqlserver服务快速打开和停止