題目:有一個合法的字符串,合法是指左括號與右括號全部能配對,現在每次將這個序列第一個左括號刪去,在將任意一個右括號刪去,每次刪去后的序列必須合法,求有多少種方法,答案對10000000007。
輸入:
一個合法括號序列。
輸出:
方案數。
樣例1:
Input:
()()()()
Output:
1
樣例2:
Input
(((())))()()
Output:
24
這題水過。。。。。。
首先我們很容易知道如果模擬的話很復雜,在進一步思考會發現從左到右走會有后效性,當前所選的右括號會決定序列是否合法且影響到下一次的選擇,既然有后效性,那就倒過來,從右往左!可以證明到右邊先選不會影響到左邊。(突然想起了一道類似的題,比較復雜,我以后會寫的。)附上簡易的證明過程:首先明確左括號是能跟任意一個其右邊的右括號匹配的,假設當前從右向左走到某一個左括號,右邊的左括號已經全部滿足了,左邊的左括號也是能夠滿足,因為當前剩下的右括號全部在右邊,也就是說現在任意選擇一個右邊的右括號與當前走到的左括號匹配都能保證剩余的右括號能與其左邊的左括號匹配,即不會影響到整個序列的合法性。定義一個ans記錄方案數(這里有個坑,ans初始值為1!!!),再定義一個tot記錄現在右邊剩余的右括號,初始值為0,遇到右括號就加1,遇到左括號就減1。思路很清晰了,代碼很容易寫出。
#include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<algorithm> #include<cmath> using namespace std; const long long mod=10000000007ll; char A[20000005]; long long ans=1; int tot; int main() { freopen("ka.in","r",stdin); freopen("ka.out","w",stdout); scanf("%s",A); int len=strlen(A); for(int i=len-1;i>=0;i--) { if(A[i]==')')tot++; else if(A[i]=='('){ ans=(ans*tot)%mod; tot--; } } printf("%I64d",ans); //printf("%lld",ans); return 0; }
博客新手,寫的不好的話請諒解>_<!