您的位置:首页 > 其它

2011NOIP普级组第四题--表达式的值(摘自洛谷题解)

2017-11-01 19:45 274 查看


题目描述

对于1 位二进制变量定义两种运算:



运算的优先级是:

先计算括号内的,再计算括号外的。

“× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算。例如:计算表达式A⊕B × C时,先计算 B × C,其结果再与 A 做⊕运算。

现给定一个未完成的表达式,例如_+(_*_),请你在横线处填入数字0 或者1 ,请问有多少种填法可以使得表达式的值为0 。


输入输出格式

输入格式:输入文件名为exp.in
,共 2 行。

第1 行为一个整数 L,表示给定的表达式中除去横线外的运算符和括号的个数。

第2 行为一个字符串包含 L 个字符,其中只包含’(’、’)’、’+’、’*’这4 种字符,其中’(’、’)’是左右括号,’+’、’*’分别表示前面定义的运算符“⊕”和“×”。这行字符按顺序给出了给定表达式中除去变量外的运算符和括号。

输出格式:

输出文件exp.out 共1 行。包含一个整数,即所有的方案数。注意:这个数可能会很大,请输出方案数对10007 取模后的结果。

输入输出样例

输入样例#1: 复制
4
+(*)


输出样例#1: 复制











说明

【输入输出样例说明】

  给定的表达式包括横线字符之后为:_+(_*_) 

  在横线位置填入(0 、0 、0) 、(0 、1 、0) 、(0 、0 、1) 时,表达式的值均为0 ,所以共有3种填法。 

【数据范围】

对于20% 的数据有 0 ≤ L ≤ 10。

对于50% 的数据有 0 ≤ L ≤ 1,000。

对于70% 的数据有 0 ≤ L ≤ 10,000 。

对于100%的数据有 0 ≤ L ≤ 100,000。

对于50% 的数据输入表达式中不含括号。

二、解题思路

本题难点在于:

1.有优先级

2.有括号

我们先分析一下

这是一道表达式计算的扩展题,对选手最基本的要求就是表达式计算。在一般的表达式计算中,存放结果的栈都是记录计算到某一步的结果,而在这道题中,结果只可能为2个(0或者1),且是知道的,而运算的数字是不一定的,所以在栈中只需存放算到0或者1时的方案数,最后输出到最后算出0的方案数即可。

算法实现

一、 首先粗略地说一下表达式计算的方法: 需要使用两个栈,一个存放结果,另一个存放符号。每次读入一个数据,就进入结果栈,如果是符号,则按以下方法: 1、 如果是左括号,就直接进栈; 2、 如果是右括号,就一直弹栈并加以计算,直到弹到左括号; 3、 如果是运算符,则弹栈,直到这个运算符的优先级大于符号栈栈顶的符号的优先级 或是左括号或栈空,然后将运算符进栈; 最后再将栈中残余的符号和结果一直弹到只剩一个结果,这个就是最后的结果。 二、 此题算法的框架整体上是和表达式计算相同的,有以下几个方面不同: 1、需要添加数字的地方应该满足不在右括号的后面或者左括号的前面
2、优先级:“*”的优先级比“+”高 3、运算方法,每一步计算为0或1的方法数:设两个步骤的运算结果经过每个符号到一个结果时,第一个运算结果算出0的方案数为t1,1的方案数为t2,第二个算出0的方案数为t3,算出1的方案数为t4,则有: 当符号是“⊕”时,得到0的方案数为t1*t3,1的方案数:t1*t4+t2*t3+t2*t4 当符号是“×”时,得到0的方案数为t1*t3+t1*t4+t2*t3,1的方案数:t2*t4 用一个栈记录下来即可

三、参考代码

#include<stdio.h>

const int M=10007,N=100005;

int n,i,u[N],v[N],top,k;

char c[N],sta[N],ans[2*N];

int main()

{

    //freopen("exp.in","r",stdin);

    //freopen("exp.out","w",stdout);

    scanf("%d\n%s",&n,c);

    ans[++k]='.';

    for(i=0;c[i];i++)

    {

        if(c[i]=='('||c[i]=='*')

            sta[++top]=c[i];

        if(c[i]=='+')

        {

            while(sta[top]=='*')

                ans[++k]=sta[top--];

            sta[++top]=c[i];

        }

        if(c[i]==')')

        {

            while(sta[top]!='(')

                ans[++k]=sta[top--];

            top--;

        }

        if(c[i]!='('&&c[i]!=')')

            ans[++k]='.';

    }

    while(top>0)

        ans[++k]=sta[top--];

    for(i=1;i<=k;i++)

    {

        if(ans[i]=='.')

        {

            u[++top]=1;

            v[top]=1;

        }

        if(ans[i]=='*')

        {

            top--;

            u[top]=(u[top+1]*v[top]+u[top]*v[top+1]+u[top]*u[top+1])%M;

            v[top]=v[top]*v[top+1]%M;

        }

        if(ans[i]=='+')

        {

            top--;

            v[top]=(u[top+1]*v[top]+u[top]*v[top+1]+v[top]*v[top+1])%M;

            u[top]=u[top]*u[top+1]%M;

        }

    }

    printf("%d",u[1]);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: