【NOIP】普及组2011 表达式的值
【算法】动态规划+后缀表达式
【题解】
先把算式转为后缀表达式后进行DP
令f[s][0]表示使表达式答案为0的方案数
f[s][1]表示使表达式答案为1的方案数
(加法)
f[a+b][1]=f[a][0]*f[b][1]+f[a][1]*f[b][0]+f[a][1]*f[b][1]
f[a+b][0]=f[a][0]*f[b][0]
(乘法)
f[a+b][0]=f[a][0]*f[b][0]+f[a][0]*f[b][1]+f[a][1]*f[b][0]
f[a+b][1]=f[a][1]*f[b][1]
【后缀表达式】
1.对符号设置优先级,即先计算的符号,一般是 () > * > + 。
2.从前往后扫描,遇到数字入数字栈顶,遇到符号入符号栈顶。
如果当前符号优先级低于栈顶符号,那么弹出栈顶符号并对数字栈顶和次顶弹出做该符号运算,结果重新作为数字栈顶。
重复直至优先级高于栈顶符号或栈空。
3.遇到左括号直接入栈,遇到右括号弹出符号栈顶直至左括号停止。
为了最后能清空符号栈,通常最开始加入左括号,最后加入右括号。
4.本题的DP其实是对数字栈DP,每次运算时对应变换DP数组f[]。
我的代码中的写法是先处理出后缀表达式(数字直接放,符号压栈),然后再用后缀表达式模拟数字栈变化。
【注意】
1.记得取模10007。
2.调试几小时的教训!在计算“+”的f[a+b][1]的时候调用了f[a+b][0],所以一定要把f[a+b][1]先计算!!!(“*”反之)T_T调得好累……
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn=,mod=;
char s[maxn*],t[maxn*],now[maxn*],c;
int lenn,lent,len,num,n;
int f[maxn][];
void jrz()
{
while(now[lenn]=='+'||now[lenn]=='*')t[++lent]=now[lenn--];
now[++lenn]='+';
}
void crz()
{
while(now[lenn]=='*')t[++lent]=now[lenn--];
now[++lenn]='*';
}
void kcz()
{
while(now[lenn]!='(')t[++lent]=now[lenn--];
lenn--;
}
void pluss()
{
f[num][]=(f[num][]*f[num+][]+f[num][]*f[num+][]+f[num][]*f[num+][])%mod;
f[num][]=(f[num][]*f[num+][])%mod;
}
void cheng()
{
f[num][]=(f[num][]*f[num+][]+f[num][]*f[num+][]+f[num][]*f[num+][])%mod;
f[num][]=(f[num][]*f[num+][])%mod;
}
void change()
{
now[]='(';lenn=;lent=-;
for(int i=;i<=len;i++)
{//printf("%d",i);
//for(int j=0;j<=lenn;j++)printf("%c",now[j]);
//printf(" lenn=%d\n",lenn);
if(s[i]=='_')t[++lent]='_';
if(s[i]=='+')jrz();
if(s[i]=='*')crz();
if(s[i]=='(')now[++lenn]='(';
if(s[i]==')')kcz();
}
kcz();//printf("lenn=%d",lenn);printf("[t]\n\n%s\n\n",t);
}
void work()
{
num=;
for(int i=;i<=lent;i++)
{
if(t[i]=='_')
{
num++;
f[num][]=;f[num][]=;
}
if(t[i]=='+')num--,pluss();//printf("f[%d][0]=%d,f[%d][1]=%d\n",num,f[num][0],num,f[num][1]);
if(t[i]=='*')num--,cheng();//printf("f[%d][0]=%d,f[%d][1]=%d\n",num,f[num][0],num,f[num][1]);
}
}
int main()
{
// freopen("exp.in","r",stdin);
// freopen("exp.out","w",stdout);
scanf("%d",&n);
c=getchar();c=getchar();
len=-;
if(c!='(')s[]='_',len=;
s[++len]=c;
for(int i=;i<=n;i++)
{
c=getchar();
if(c!='('&&s[len]!=')')s[++len]='_';
s[++len]=c;
}
if(c!=')')s[++len]='_';
// printf("\n\n%s\n\n",s);
change();
work();
printf("%d",f[][]);
return ;
}
【NOIP】普及组2011 表达式的值的更多相关文章
- NOIP 普及组 2013 表达式求值
传送门 https://www.cnblogs.com/violet-acmer/p/9898636.html 题解: 哇哇哇,又是一发暴力AC. 用字符数组存储表达式. 然后将表达式中的 数字 与 ...
- [NOIP普及组2011]装箱问题
目录 链接 博客链接 题目链接 题目内容 题目描述 格式 输入 输出 样例 输入 输出 前缀知识 题解 题目名称:装箱问题 来源:2011年NOIP普及组 链接 博客链接 CSDN 洛谷博客 题目链接 ...
- NOIP2013普及组 T2 表达式求值
OJ地址:洛谷P1981 CODEVS 3292 正常写法是用栈 #include<iostream> #include<algorithm> #include<cmat ...
- [NOIp普及组2011]瑞士轮
洛谷题目链接:瑞士轮 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较 ...
- 数字反转 NOIp普及组2011
当数字位数不确定时,如何反转呢? 本文为博客园ShyButHandsome原创作品,转载请注明出处 使用右侧目录快速浏览文章 题目描述 给定一个整数,请将该数各个位上数字反转得到一个新数. 新数也应满 ...
- 2016.8.15上午纪中初中部NOIP普及组比赛
2016.8.15上午纪中初中部NOIP普及组比赛 链接:https://jzoj.net/junior/#contest/home/1333 这次比赛不怎么好,因为这套题目我并不是很擅长. 可同学们 ...
- 2016.8.17上午纪中初中部NOIP普及组比赛
2016.8.17上午纪中初中部NOIP普及组比赛 链接:https://jzoj.net/junior/#contest/home/1335 本来觉得自己能考高分,但只得160分,并列第九.至少又挤 ...
- 2016.9.24初中部上午NOIP普及组比赛总结
2016.9.24初中部上午NOIP普及组比赛总结 2016.09.24[初中部 NOIP普及组 ]模拟赛 其实这次我没比赛,早上去参加亲子活动去了. 不过在下午我做完了所有的题,感觉还好. 进度 现 ...
- 2321. 【NOIP普及组T1】方程
2321. [NOIP普及组T1]方程 时间限制: 1000 ms 空间限制: 262144 KB 题目描述
随机推荐
- 全排列 next_permutation() 函数的用法
在头文件<algorithm>里面有如下代码: int a[]; do { } while(next_permutation(a,a+n)); 可产生1~n的全排列有如下代码: #incl ...
- C# Designer.cs
designer.cs 是窗体设计器生成的代码文件,作用是对窗体上的控件做初始化工作(在函数InitializeComponent()中) VS2003以前都把这部分代码放到窗体的cs文件中,由于这部 ...
- Pandas速查手册中文版(转)
关键缩写和包导入 在这个速查手册中,我们使用如下缩写: df:任意的Pandas DataFrame对象 同时我们需要做如下的引入: import pandas as pd 导入数据 pd.read_ ...
- BZOJ4709 JSOI2011柠檬(动态规划)
首先要冷静下来发现这仅仅是在划分区间.显然若有相邻的数字相同应当划分在同一区间.还有一个显然的性质是区间的两端点应该相同且选择的就是端点的数.瞬间暴力dp就变成常数极小100002了.可以继续斜率优化 ...
- 【刷题】UOJ #79 一般图最大匹配
从前一个和谐的班级,所有人都是搞OI的.有 \(n\) 个是男生,有 \(0\) 个是女生.男生编号分别为 \(1,-,n\) . 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个 ...
- Android 解决setRequestedOrientation之后手机屏幕的旋转不触发onConfigurationChanged方法
最近在做播放器的时候遇到一个问题,在屏幕方向改变之后需要切换播放器全屏/非全屏的时候,在重写了onConfigurationChanged方法并在manifest.xml配置文件中添加 android ...
- HDOJ.1228 A + B (map)
A + B 点我挑战题目 点我一起学习STL-MAP 题意分析 讲字符串和数字用map对应即可 代码总览 /* Title:HDOJ.1228 Author:pengwill Date:2016-11 ...
- [BZOJ1131/POI2008]Sta树的深度
Description 给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大 Input 给出一个数字N,代表有N个点.N<=1000000 下面N-1条边. Output ...
- luoguP1357 花园
矩阵乘法优化dp 注意环形处理: 发现,对于一个初始状态s的方案数,就是填n次后,再回到自己的状态.期间都是合法的话,那么一定这个方案就合法. 和开始状态有关.所以先把状态转移矩阵的(n-m)乘出来. ...
- contOS镜像快速加载到本地虚拟机软件
无需任何配置,只要两步: 1.首先打开 虚拟机软件VMware 2.然后打开镜像目录,找到后缀名为 .vmx 的文件,双击,即可. 会自动 挂载好,如下图: