zoukankan      html  css  js  c++  java
  • NOIP 2011 普及组 T4 表达式的值 栈

    题目

    题目描述

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

    运算的优先级是:

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

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

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

    输入输出格式

    输入格式:

    共 2 行。

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

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

    输出格式:

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

    输入输出样例

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

    说明

    【输入输出样例说明】

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

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

    【数据范围】

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

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

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

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

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

    分析

    首先这道题目,我们要先搞清楚我们如何从前往后退出答案。可以肯定的是,在出现某个特定符号的时候,我们要知道如何从已知答案中推出之后的答案。这其实就是一个用公式递推的过程。每一步计算下一步答案为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 用一个栈记录下来即可。

    然后按以下方法计算:

    1. 如果是左括号,就直接进栈;
    2. 如果是右括号,就一直弹栈并加以计算,直到弹到左括号;
    3. 如果是运算符,则弹栈,直到这个运算符的优先级大于符号栈栈顶的符号的优先级 或是左括号或栈空,然后将运算符进栈; 最后再将栈中残余的符号和结果一直弹到只剩一个结果,这个就是最后的结果。

    程序

     1 #include <bits/stdc++.h>
     2 const int M=10007,N=100005;
     3 int n, u[N], v[N], top, k;
     4 char c[N], S[N], ans[2*N];
     5 int main()
     6 {
     7     scanf("%d",&n);
     8     scanf("%s",c);
     9     ans[++k]='.';
    10     for(int i = 0; c[i]; i++)
    11     {
    12         if(c[i] == '(' || c[i] == '*')
    13             S[++top] = c[i];
    14         if(c[i] == '+')
    15         {
    16             while(S[top] == '*')
    17                 ans[++k] = S[top--];
    18             S[++top] = c[i];
    19         }
    20         if(c[i] == ')')
    21         {
    22             while(S[top] != '(')
    23                 ans[++k] = S[top--];
    24             top--;
    25         }
    26         if(c[i] != '(' && c[i] != ')')
    27             ans[++k]='.';
    28     }
    29     while(top > 0)
    30         ans[++k] = S[top--];
    31     for(int i = 1; i <= k; i++)
    32     {
    33         if(ans[i] == '.')
    34         {
    35             u[++top] = 1;
    36             v[top] = 1;
    37         }
    38         if(ans[i] == '*')
    39         {
    40             top--;
    41             u[top] = (u[top+1]*v[top]+u[top]*v[top+1]+u[top]*u[top+1])%M;
    42             v[top] = v[top]*v[top+1]%M;
    43         }
    44         if(ans[i] == '+')
    45         {
    46             top--;
    47             v[top] = (u[top+1]*v[top]+u[top]*v[top+1]+v[top]*v[top+1])%M;
    48             u[top] = u[top]*u[top+1]%M;
    49         }
    50     }
    51     printf("%d",u[1]);
    52     return 0;
    53 }
  • 相关阅读:
    test
    linux安装web服务小总结-用户和权限
    linux安装pure-ftpd和配置
    空值等
    学习laravel
    vb窗体内获取窗体内坐标颜色值
    自从我安装卸载几次OFFICE和WPS后,VB6就出现了这样的问题。
    VB动态添加WebBrowser控件,并拦截弹出窗口(不用引用任何组件)
    部件ieframe.dll或其附件之一不能正确注册:一个文件丢失或无效
    修改组策略,轻松控制游戏许可权。
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/9226692.html
Copyright © 2011-2022 走看看