【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.记得取模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=150010,mod=10007;
char s[maxn*2],t[maxn*2],now[maxn*2],c;
int lenn,lent,len,num,n;
int f[maxn][2];
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][1]=(f[num][0]*f[num+1][1]+f[num][1]*f[num+1][0]+f[num][1]*f[num+1][1])%mod;
    f[num][0]=(f[num][0]*f[num+1][0])%mod;
}
void cheng()
{
    f[num][0]=(f[num][0]*f[num+1][1]+f[num][1]*f[num+1][0]+f[num][0]*f[num+1][0])%mod;
    f[num][1]=(f[num][1]*f[num+1][1])%mod;
}
void change()
{
    now[0]=‘(‘;lenn=0;lent=-1;
    for(int i=0;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=0;
    for(int i=0;i<=lent;i++)
     {
         if(t[i]==‘_‘)
          {
              num++;
              f[num][0]=1;f[num][1]=1;
          }
         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=-1;
    if(c!=‘(‘)s[0]=‘_‘,len=0;
    s[++len]=c;
    for(int i=2;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[1][0]);
    return 0;
}

时间: 2024-10-14 02:21:51

【NOIP】普及组2011 表达式的值的相关文章

纪中10日T1 2300. 【noip普及组第一题】模板题

2300. [noip普及组第一题]模板题 (File IO): input:template.in output:template.out 时间限制: 1000 ms  空间限制: 262144 KB  具体限制 题目描述 输入 输出 样例输入 样例输出 数据范围限制 朴素算法 考试开始的前一个小时我一直在折腾朴素算法 -> 对拍 1 #pragma GCC optimize(2) 2 #include<bits/stdc++.h> 3 #define IL inline 4 usin

NOIP普及组2015 T1金币

我对模拟的理解:http://www.cnblogs.com/AKMer/p/9064018.html 题目链接:https://www.luogu.org/problemnew/show/P2669 这是我OI生涯中第一场比赛的第一道题目,而且这题在2015的普及组之前我就做过了(当时教练说NOIP会从NOI题库里选原题就狂刷了一通emmm).只需根据它的题意模拟按阶段发金币,然后特判最后一个阶段是否会全部发完就可以了,水的不能再水.代码如下: 1 #include <cstdio> 2 #

2011表达式的值

题目描述 Description 对于 1 位二进制变量定义两种运算:运算符 运算规则⊕0⊕0=00⊕1=11⊕0=11⊕1=1×0 × 0=00 × 1=01 × 0=01 × 1=1 运算的优先级是:1. 先计算括号内的,再计算括号外的.2. “×”运算优先于“⊕”运算,即计算表达式时,先计算×运算,再计算⊕运算.例如:计算表达式A⊕B × C 时,先计算B × C,其结果再与A 做⊕运算.现给定一个未完成的表达式,例如_+(_*_),请你在横线处填入数字0 或者1,请有多少种填法可以使得表

CODEVS3294 车站分级 noip普及组T4

题目描述 Description 一条单向的铁路线上,依次有编号为1, 2, …, n的n个火车站.每个火车站都有一个级别,最低为1级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车站x,则始发站.终点站之间所有级别大于等于火车站x的都必须停靠.(注意:起始站和终点站自然也算作事先已知需要停靠的站点)例如,下表是5趟车次的运行情况.其中,前4趟车次均满足要求,而第5趟车次由于停靠了3号火车站(2级)却未停靠途经的6号火车站(亦为2级)而不满足要求. 现有m趟车次的运

NOIP普及组初赛笔记

先序遍历:首先访问根结点然后遍历左子树,最后遍历右子树.在遍历左.右子树时,仍然先访问根结点,然后遍历左子树,最后遍历右子树,如果二叉树为空则返回. 中序遍历:中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树.在遍历左.右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树. 后序遍历:后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左.右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点. [例1]若一个无向完全图有7个顶点,则共有_____条边 资料:无向完全图是

NOIP 普及组 T4 子矩阵(--洛谷P2258)

题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第2.4行和第2.4.5列交叉位置的元素得到一个2*3的子矩阵如右图所示. 9 3 3 3 9 9 4 8 7 4 1 7 4 6 6 6 8 5 6 9 7 4 5 6 1 的其中一个2*3的子矩阵是 4 7 4 8 6 9 相邻的元素:矩阵中的某个元素与其上下左右四个元素(如果存在的话)是相邻的. 矩阵的分值:矩阵中每一对相邻元素之差

noip普及组2004 FBI树

FBI树 描述 我们可以把由"0"和"1"组成的字符串分为三类:全"0"串称为B串,全"1"串称为I串,既含"0"又含"1"的串则称为F串. FBI树是一种二叉树1,它的结点类型也包括F结点,B结点和I结点三种.由一个长度为2^N的"01"串S可以构造出一棵FBI树T,递归的构造方法如下:1) T的根结点为R,其类型与串S的类型相同:2) 若串S的长度大于1,将串S从

noip提高组2011 Mayan游戏

Mayan游戏 描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.**游戏通关是指在规定的步数内消除所有的方块,**消除方块的规则如下: 1.每步移动可以且仅可以沿横向(即向左或向右)拖动某一方块一格:当拖动这一方块时,如果拖动后到达的位置(以下称目标位置)也有方块,那么这两个方块将交换位置(参见图6到图7):如果目标位置上没有方块,那么被拖动的方块将从原来的竖列中抽出,并从

noip普及组2007 纪念品分组

纪念品分组 描述 元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作.为使得参加晚会的同学所获得 的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品, 并且每组纪念品的价格之和不能超过一个给定的整数.为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少. 你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目. [限制] 50%的数据满足: 1 <=n <= 15 100%的数据满足: 1 <= n <= 30