NOIP 2011 普及組 T4 表達式的值 棧
題目
題目描述
對於1 位二進制變量定義兩種運算:
運算的優先級是:
-
先計算括號內的,再計算括號外的。
-
“× ”運算優先於“⊕”運算,即計算表達式時,先計算× 運算,再計算⊕運算。例如:計算表達式A⊕B × C時,先計算 B × C,其結果再與 A 做⊕運算。
現給定一個未完成的表達式,例如_+(_*_),請你在橫線處填入數字 00 0 或者 111 ,請問有多少種填法可以使得表達式的值為 00 0 。
輸入輸出格式
輸入格式:共 2 行。
第1 行為一個整數 LLL ,表示給定的表達式中除去橫線外的運算符和括號的個數。
第2 行為一個字符串包含 LLL 個字符,其中只包含’(’、’)’、’+’、’*’這 444 種字符,其中’(’、’)’是左右括號,’+’、’*’分別表示前面定義的運算符“⊕”和“×”。這行字符按順序給出了給定表達式中除去變量外的運算符和括號。
共1 行。包含一個整數,即所有的方案數。註意:這個數可能會很大,請輸出方案數對 1000710007 10007 取模後的結果。
輸入輸出樣例
輸入樣例#1: 復制4 +(*)輸出樣例#1: 復制
3
說明
【輸入輸出樣例說明】
給定的表達式包括橫線字符之後為:_+(_*_)
在橫線位置填入(0 、0 、0) 、(0 、1 、0) 、(0 、0 、1) 時,表達式的值均為0 ,所以共有3種填法。
【數據範圍】
對於 20%20\%20% 的數據有 0≤L≤10 0 ≤ L ≤ 100≤L≤10 。
對於 50%50\%50% 的數據有 0≤L≤1,0000 ≤ L ≤ 1,0000≤L≤1,000 。
對於 70%70\%70% 的數據有 0≤L≤10,000 0 ≤ L ≤ 10,0000≤L≤10,000 。
對於 100%100\%100% 的數據有 0≤L≤100,000 0 ≤ L ≤ 100,0000≤L≤100,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 #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 表達式的值 棧