洛谷P1310 表达式的值——题解



题的难点:1、有运算优先级,不好判断。2、有破坏整体和谐性的讨厌的括号。3、不知道哪里要填数。4、要求方案数很大,搜索不会做呐。
发现难点1和2都是中缀表达式的缺点。转成后缀表达式后难点1、2就烟消云散了。
普及一下:
前缀表达式(又称波兰表达式)与后缀表达式(又称逆波兰表达式)较我们平常使用的中缀表达式,最主要的特点是没有括号。前/后缀表达式是一种十分有用的表达式,将中缀表达式转换为前缀表达式后,就可以只依靠出栈、入栈两种简单操作完全解决中缀表达式的全部运算。而平常我们一般都用后缀表达式(顺序从前到后,而前缀表达式的扫描顺序是从后向前)。
计算后缀表达式,只要我们从前到后扫描,遇到数就入栈,遇到运算符就出栈两个数进行相应运算,最终弄结果再入栈。
这里给出一个中缀表达式转后缀表达式的方法(建树什么的就别提了):
设用一个结果栈和一个符号栈。从前向后扫描中缀表达式:
1、若遇到数,直接入结果栈;
2、若遇到运算符,弹出符号栈栈顶连续的优先级高于它的运算符,让那些运算符按弹出顺序依次入结果栈后再自己入符号栈;
3、若遇到左括号,直接入符号栈;
4、若遇到右括号,一直弹出符号栈至第一次弹出左括号,将弹出的运算符(不包括括号)按弹出顺序依次入结果栈;
5、若扫描完中缀表达式后符号栈栈非空,则将符号栈元素全部弹出,将弹出的运算符按弹出顺序依次入结果栈。
最后结果栈存的就是转换完的后缀表达式。计算时只要从结果栈的栈底开始扫,按照后缀表达式的计算过程计算即可。
再考虑从哪里填数。发现当我们无视括号时,剩下运算符的前后都会有一个数、相邻两运算符间也会有一个数。加上括号后只会改变运算顺序,不会改变数的数量。考虑起始时在结果栈先入一个数,每次遇到加号或乘号后再入一个数。辩证正确性:如果该加号(或乘号)后面有括号时:若为左括号,由于左括号直接入符号栈,所以入左括号进符号栈和入数进结果栈这两步操作的顺序无关紧要;若为右括号,那么该运算符后面就应该有一个数。如果该加号(或乘号)后面没有括号时,后面就该有一个数。辩证结束。
由于题目中要求的是最终表达式值为0的方案数,发现可由每次运算结果为0的方案数和结果为1的方案数推出: 设某运算符左边为1的方案数有l1种、为零的方案数有l0种;右边为1的方案数有r1种,右边为0的方案数有r0种。若该运算符为+,则结果为1的方案数则有l1*r1+l0*r1+l1*r2种,结果为0的方案数则有l0*r0种;若该运算符为*,则结果为1的方案数则有l1*r1种,结果为0的方案数则有l1*r0+l0*r0+l0*r1种。由此可以增设两个栈zero、one,分别维护随着结果栈进行运算时运算符左右两边为0的方案数和为1的方案数。思路就到此为止了。
见AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stack> using namespace std; int lenl; const int mod=; char exp[];//一开始输入的中缀表达式 string pol="n";//用'n'代替要填的数。pol为结果栈,但发现用string更好维护,于是就换成了string型。 stack<char> sta;//符号栈 stack<int>zero,one,ope;//zero、one的意义见上文,ope为计算后缀表达式时用到的辅助栈 int main()
{
cin>>lenl;
scanf("%s",exp);
for(int k=;k<lenl;k++)//中缀表达式转后缀表达式
{
if(exp[k]=='*'||exp[k]=='(')
sta.push(exp[k]);
if(exp[k]=='+')
{
while(!sta.empty()&&sta.top()=='*')
{
pol+='*';
sta.pop();
}
sta.push('+');
}
if(exp[k]==')')
{
while(sta.top()!='(')
{
pol+=sta.top();
sta.pop();
}
sta.pop();
}
if(exp[k]=='*'||exp[k]=='+') pol+='n';//填数
}
while(!sta.empty())//别忘了把符号栈剩余的元素转到结果里
{
pol+=sta.top();
sta.pop();
}
int l0,r0,l1,r1;
for(int k=;k<pol.length();k++)//计算后缀表达式
{
if(pol[k]=='n')
{
zero.push();
one.push();
}
if(pol[k]=='+')
{
l0=zero.top();zero.pop();
l1=one.top();one.top();
r0=zero.top();zero.pop();
r1=one.top();one.top();
zero.push(l0*r0%mod);
one.push(((l0*r1+l1*r0)%mod+l1*r1)%mod);
}
if(pol[k]=='*')
{
l0=zero.top();zero.pop();
l1=one.top();one.top();
r0=zero.top();zero.pop();
r1=one.top();one.top();
zero.push(((l0*r0+l1*r0)%mod+l0*r1)%mod);
one.push(l1*r1%mod);
}
}
cout<<zero.top();//最终使表达式值为零的方案数
return ;
}
做这个题时如果不会转中缀表达式转后缀表达式的话模拟也是可以骗点分的,但要注意考虑周全。(就算是一点微不足道的手误,也能造就90分到10分的神话(说多了都是泪))
洛谷P1310 表达式的值——题解的更多相关文章
- 2019.06.17课件:[洛谷P1310]表达式的值 题解
P1310 表达式的值 题目描述 给你一个带括号的布尔表达式,其中+表示或操作|,*表示与操作&,先算*再算+.但是待操作的数字(布尔值)不输入. 求能使最终整个式子的值为0的方案数. 题外话 ...
- 洛谷P1310 表达式的值 题解 栈/后缀表达式的应用
题目链接:https://www.luogu.org/problem/P1310 本题涉及算法:栈.前缀表达式转后缀表达式,动态规划思想. 这道题目我思考了好长时间,第一时间让我做的话我也做不出来. ...
- 洛谷 P1310 表达式的值 解题报告
P1310 表达式的值 题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. "× "运算优先于"⊕"运算,即计算表 ...
- 洛谷P1310 表达式的值
P1310 表达式的值 题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例 ...
- 【洛谷P1310 表达式的值】
题目链接 题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式 ...
- 洛谷P1981 表达式求值 题解 栈/中缀转后缀
题目链接:https://www.luogu.org/problem/P1981 这道题目就是一道简化的中缀转后缀,因为这里比较简单,只有加号(+)和乘号(*),所以我们只需要开一个存放数值的栈就可以 ...
- 洛谷 P1981 表达式求值
P1981 表达式求值 题目描述 给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值. 输入输出格式 输入格式: 输入文件为 expr.in. 输入仅有一行,为需要你计算的表达式,表达式中只 ...
- 题解-洛谷P1981 表达式求值(模拟+处理优先级的递归)
https://www.luogu.org/problemnew/show/P1981 (原题链接) 显然乘法的优先级高与加法,因此碰到乘号就要优先把一连串与乘号相连的数算出,很容易想到递归.可用普通 ...
- 洛谷 P5146 最大差值 题解
P5146 最大差值 题目描述 HKE最近热衷于研究序列,有一次他发现了一个有趣的问题: 对于一个序列\(A_1,A_2\cdots A_n\),找出两个数\(i,j\),\(1\leq i< ...
随机推荐
- 关于cors 跨域的一些问题
system.webServer节点写配置 <httpProtocol> <customHeaders> <add name="Access-Control-A ...
- 【转】mysqldump原理探究
作者:胡儿胡儿 来源:CSDN 原文:https://blog.csdn.net/cug_jiang126com/article/details/49824471 —————————————————— ...
- pyhton之解析html的表格
#!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = 'jiangwenwen' from bs4 import BeautifulS ...
- 从汇编到C
一. 设置栈 1.1. C语言运行时需要和栈的意义 1.1.1. “C语言运行时(runtime)”需要一定的条件,这些条件由汇编来提供.C语言运行时主要是需要栈 1.1.2. C语言与栈的关系 a. ...
- django商城项目之用sentry管理日志
之前写商城项目的时候,采用的日志处理方式为在终端输出或者写入文件,这样的话,项目部署上线之后,若服务器出现错误,需要到服务器查看相关的错误日志,很不方便.后期在学习别人开源项目的时候,学习到一个开源的 ...
- Android remote gdb
On Android phone adb push ~/utils/android-ndk-r12b/prebuilt/android-arm64/gdbserver/gdbserver /data/ ...
- 0ctf 2017 kernel pwn knote write up
UAF due to using hlist_add_behind() without checking. There is a pair locker(mutex_lock) at delete_n ...
- SCUT - 484 - 平面上的点 - 数据结构
https://scut.online/p/484 一开始想的是按固定斜率的直线从无穷扫下来,但是一直都WA,不知道是哪里错了还是精度问题? #include<bits/stdc++.h> ...
- 计算机系统结构总结_Instruction Set Architecture
Textbook:<计算机组成与设计——硬件/软件接口> HI<计算机体系结构——量化研究方法> QR 这节我们来看CPU内部的一些东西. Instruct ...
- django后台返回html字段会产生XSS防护的解决方式
1.在前端模块里面写 {{ page_str|safe }} 2.在后端 from django.utils.safestring import mark_safe pake_str = mark_ ...