1. 程式人生 > >NOIP 2011 普及組 T4 表達式的值 棧

NOIP 2011 普及組 T4 表達式的值 棧

字符串包含 pri 進制 字符 bits range 一個 DC 一個棧

題目

題目描述

對於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 }

NOIP 2011 普及組 T4 表達式的值 棧