【NOIP2011普及组复赛】题4:表达式的值

题4:表达式的值

【题目描述】

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

在这里插入图片描述

运算的优先级是:

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

  2. “ × ” “×” × 运算优先于 “ ⊕ ” “⊕” 运算,即计算表达式时,先计算 × × ×运算,再计算 ⊕ ⊕ 运算。

例如:计算表达式 A ⊕ B × C A⊕B × C AB×C 时,先计算 B × C B × C B×C,其结果再与 A A A ⊕ ⊕ 运算。

现给定一个未完成的表达式,例如 + ( ∗ ) +(*) +(),请你在横线处填入数字 0 0 0 或者 1 1 1,请问

有多少种填法可以使得表达式的值为 0 0 0

【输入文件】

2 2 2 行。

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

2 2 2 行为一个字符串包含 L L L 个字符,其中只包含 ’(’、’)’、’ + ’、’ ∗ ’ ’(’、’)’、’+’、’*’ + 4 4 4 种字符,其中 ’(’、’)’ ’ (’、’)’ 是左右括号, ’ + ’、’ ∗ ’ ’+’、’*’ + 分别表示前面定义的运算符 “ ⊕ ” “⊕” “ × ” “×” ×。这行字符按顺序

给出了给定表达式中除去变量外的运算符和括号。

【输出文件】

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

【输入样例1】

4
+(*)

【输出样例1】

3

【样例说明】

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

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

【数据范围】

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

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

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

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

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

【代码如下】:

#include <bits/stdc++.h>
using namespace std;
struct dp {
  int zero, one;
} ans[150001];
int len, t = 1;
const int mod = 10007;
string str;
stack<char> s;
inline void dispose(char ch, dp &a, dp &b) {
  if (ch == '+') {
    a.one = (a.one * (b.zero + b.one) + a.zero * b.one) % mod;
    a.zero = a.zero * b.zero % mod;
  } else {
    a.zero = (a.zero * (b.zero + b.one) + a.one * b.zero) % mod;
    a.one = a.one * b.one % mod;
  }
}
int main() {
  cin >> len >> str;
  str += ')';
  ans[1].zero = ans[1].one = 1;
  s.push('(');
  for (int i = 0; i <= len; i++)
    if (str[i] == '(')
      s.push('(');
    else if (str[i] == ')') {
      for (; s.top() != '('; s.pop(), t--) dispose(s.top(), ans[t - 1], ans[t]);
      s.pop();
    } else {
      for (; s.top() <= str[i] && s.top() != '('; s.pop(), t--)
        dispose(s.top(), ans[t - 1], ans[t]);
      s.push(str[i]);
      ans[++t].zero = 1;
      ans[t].one = 1;
    }
  cout << ans[1].zero;
  return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lpstudio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值