码迷,mamicode.com
首页 > 其他好文 > 详细

【NOIP】普及组2011 表达式的值

时间:2016-08-13 21:11:23      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:

【算法】动态规划+后缀表达式

【题解】

先把算式转为后缀表达式后进行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;
}
View Code

 

【NOIP】普及组2011 表达式的值

标签:

原文地址:http://www.cnblogs.com/onioncyc/p/5768763.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!