題解html
1.假設有兩個布爾變量 x , y c++
x0表示使得x=0的方案數spa
x1表示使得x=1的方案數code
y0表示使得y=0的方案數htm
y1表示使得y=1的方案數blog
| 按位或 | & 按位與 |
0 0 -> 0 | 0 0 -> 0 |
0 1 -> 1 | 0 1 -> 0 |
1 0 -> 1 | 1 0 -> 0 |
1 1 -> 1 | 1 1 -> 1 |
then, get
x | y=0 方案數爲 x0*y0string
x | y=1 方案數爲 x0*y1+x1*y0+x1*y1it
x & y=0 方案數爲 x0*y1+x1*y0+x0*y0 table
x & y=1 方案數爲 x1*y1
2.中綴轉後綴規則
考慮用棧維護。
遍歷中綴表達式:
遇到數字,直接放入答案序列
遇到左括號,入棧
最後把棧裏剩下的元素依次放入答案序列
代碼
#include<bits/stdc++.h> using namespace std; const int mod=1e4+7; const int maxn=1e5+5; int n; char zhong[maxn]; //輸入的中序遍歷 stack<char>sta; //棧 string hou; //轉化的後綴表達式 stack<int> zero,one; //答案爲0的方案數,答案爲1的方案數 int main() { scanf("%d",&n); scanf("%s",zhong+1); //下標從1開始 hou.push_back('n'); //後綴表達式裏一開始要有一個未知數 //中綴轉後綴 for(int i=1;i<=n;i++) { if(zhong[i]=='('||zhong[i]=='*') sta.push(zhong[i]); if(zhong[i]=='+') { while(!sta.empty()&&sta.top()=='*') { hou.push_back(sta.top()); sta.pop(); } sta.push(zhong[i]); } if(zhong[i]==')') { while(sta.top()!='(') { hou.push_back(sta.top()); sta.pop(); } sta.pop(); //彈出'(' } if(zhong[i]!='('&&zhong[i]!=')') hou.push_back('n'); //放入一個未知變量 } //棧裏面剩餘的存入後綴 while(!sta.empty()) { hou.push_back(sta.top()); sta.pop(); } //遍歷後綴 for(int i=0;i<hou.size() ;i++) { char c=hou[i]; if(c=='n') { zero.push(1); one.push(1); } else { int rone=one.top(),rzero=zero.top(); one.pop(); zero.pop(); //rone->y1 , rzero->y0 int lone=one.top(),lzero=zero.top(); one.pop(); zero.pop(); //lone->x1 , lzero->x0 if(c=='*') { one.push(lone*rone%mod); zero.push((lone*rzero%mod+lzero*rone%mod+lzero*rzero%mod)%mod); } else { one.push((lone*rone%mod+lone*rzero%mod+lzero*rone%mod)%mod); zero.push(lzero*rzero%mod); } } } printf("%d",zero.top()); //輸出答案 return 0; }
Thanks