[dp] Jzoj P5804 简单的序列
生活随笔
收集整理的這篇文章主要介紹了
[dp] Jzoj P5804 简单的序列
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Description
從前有個括號序列 s,滿足 |s| = m。你需要統(tǒng)計括號序列對 (p, q) 的數(shù)量。其中 (p, q) 滿足 |p| + |s| + |q| = n,且 p + s + q 是一個合法的括號序列。
Input
從文件 bracket.in?中讀入數(shù)據(jù)。第一行兩個正整數(shù) n, m。第二行一個長度為 m 的括號序列,表示 s。
?
Output
輸出到文件 bracket.out 中。輸出一行一個整數(shù),表示符合條件的 (p, q) 的數(shù)量對 10^9?+ 7 取模的值。
?
?
Sample Input
【樣例 1 輸入】 4 1 ( 【樣例 2?輸入】 4 4 (()) 【樣例 3?輸入 4 3 (((
Sample Output
【樣例 1?輸出】 4 【樣例 2?輸出】 1 【樣例 3 輸出】 0
Data Constraint
對于 10% 的數(shù)據(jù),n?≤ 20;對于 25% 的數(shù)據(jù),n?≤ 200;
對于另外 5% 的數(shù)據(jù),n?= m;
對于 55% 的數(shù)據(jù),n ? m ≤ 200;
對于 100% 的數(shù)據(jù),1 ≤ m ≤ n ≤ 10^5, n ? m ≤ 2000。
?
題解
- 我們可以把左括號看成+1,右括號看成-1
- 那么一個合法的括號序列就是左括號>=右括號
- 設(shè)f[i][j]為長度為i的序列 左括號比右括號多j個 的方案數(shù)
- 狀態(tài)轉(zhuǎn)移方程明顯就是:f[i-1][j-1]+f[i-1][j+1]
- 那么考慮如何求最終的方案數(shù)
- 首先要滿足左括號多于右括號,和?|p| + |s| + |q| = n
- 每次枚舉一個i表示前面的p序列的長度,再枚舉一個j表示p序列左括號比右括號多的個數(shù)
- 那么就是f[i][j]*f[n-m-i][j+tot](tot為原來序列中左括號比右括號多的個數(shù))
代碼
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 const long long mo=1e9+7; 7 int n,m,tot,ltot; 8 char s[100010]; 9 long long ans,f[2010][2010]; 10 int main() 11 { 12 freopen("bracket.in","r",stdin); 13 freopen("bracket.out","w",stdout); 14 scanf("%d%d",&n,&m); 15 scanf("%s",s); 16 for (int i=0;i<m;i++) 17 { 18 if (s[i]=='(') tot++; else tot--; 19 if (i==0) ltot=tot; else ltot=min(tot,ltot); 20 } 21 f[0][0]=1; 22 for (int i=1;i<=n-m;i++) 23 for (int j=0;j<=i;j++) 24 if (j==0) f[i][j]=f[i-1][j+1]; 25 else f[i][j]=(f[i-1][j-1]+f[i-1][j+1])%mo; 26 for (int i=0;i<=n-m;i++) 27 for (int j=0;j<=i;j++) 28 if (j+tot<=n-m&&j+ltot>=0) 29 (ans+=f[i][j]*f[n-m-i][j+tot])%=mo; 30 printf("%lld",ans); 31 return 0; 32 }
?
轉(zhuǎn)載于:https://www.cnblogs.com/Comfortable/p/9464185.html
總結(jié)
以上是生活随笔為你收集整理的[dp] Jzoj P5804 简单的序列的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个防弹少年团qq个性签名!
- 下一篇: python3对比python2的更新点