题目链接:
codeforces 629C Famil Door and Brackets
题目描述:
给出完整的括号序列长度n,现在给出一个序列s长度为m。枚举串p,q,使得p+s+q是合法的括号串,长度为n,问p,q的取值数目。
解题思路:
枚举p的长度,可以直接得到q的长度。因为要满足在任意位置‘(‘ 数目大于 ’)‘ 的数目,所以统计一下s串中 ’(‘ - ‘)‘ 的最小数目minx。dp[i][j] 代表 到位置 i 时,满足 ‘(‘ - ‘)‘ == j 的情况数目。然后枚举p的 j (i > -minx), 然后根据p串推出q串满足合法串的状态,两者相乘。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef __int64 LL; 5 const int INF = 1e9 + 7; 6 const int maxn = 100010; 7 const int N = 2100; 8 const int mod = 1e9+7; 9 10 11 ///dp[i][j] 到第i个位置,有j个不平衡(括号 12 LL dp[N][N], n, m; 13 char str[maxn]; 14 15 void init () 16 { 17 int num = 2010; 18 memset (dp, 0, sizeof(dp)); 19 dp[0][0] = 1; 20 21 for (int i=1; i<=num; i++) 22 for (int j=0; j<=i; j++) 23 { 24 if (j > 0) 25 dp[i][j] = (dp[i][j] + dp[i-1][j-1]) % mod; 26 dp[i][j] = (dp[i][j] + dp[i-1][j+1]) % mod; 27 } 28 } 29 30 LL solve () 31 { 32 int minx = INF, tmp = 0, num = n - m; 33 34 for (int i=0; str[i]; i++) 35 { 36 if (str[i] == ‘(‘) 37 tmp ++; 38 else 39 tmp --; 40 minx = min (minx, tmp); 41 } 42 43 LL ans = 0; 44 for (int i=0; i<=num; i++) 45 for (int j=0; j<=i; j++) 46 if (j >= -minx && num-i >= j + tmp) 47 ans = (ans + dp[i][j]*dp[num-i][j+tmp]) % mod; 48 49 return ans; 50 } 51 52 int main () 53 { 54 init (); 55 while (scanf ("%I64d %I64d", &n, &m) != EOF) 56 { 57 scanf ("%s", str); 58 printf ("%I64d\n", solve ()); 59 } 60 return 0; 61 }
时间: 2024-12-15 07:30:48