题目链接;
Codeforces 629 C Famil Door and Brackets
题意:
给一个长度为 m 的且只含
求总的构造方案数。答案对 1e9+7 取模。
数据范围: 1≤m≤n≤100000,n−m≤2000
分析:
不妨将前缀左括号数量减去右括号数量的差值称为前缀和。那么题意就是任意位置前缀和非负。首先我们可以得到给出的长度为 m 的字符串的最小前缀和
考虑在这个长度为 m 的字符串前面安排长度为
用 dp[i][j] 表示长度为 i 的串前缀和为
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <climits>
#include <cmath>
#include <ctime>
#include <cassert>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N = 100010;
const int MAX_M = 2010;
const ll mod = (ll)(1e9) + 7;int n, m;
char s[MAX_N];
ll dp[MAX_M][MAX_M];int main()
{while(~scanf("%d%d", &n, &m)) {scanf("%s", s);int Min = MAX_N, tmp = 0;for (int i = 0; i < m; ++i) {if (s[i] == '(') tmp++;else tmp--;Min = min(Min, tmp); }int diff = n - m;//printf("tmp = %d diff = %d Min = %dn", tmp, diff, Min);if((n & 1) || tmp > diff || -tmp > diff) {printf("0n");continue;}memset(dp, 0, sizeof(dp));dp[0][0] = 1;dp[1][0] = 0, dp[1][1] = 1;for (int i = 2; i <= diff; ++i) {for (int j = 0; j <= i; ++j) {if(j == 0) dp[i][j] = dp[i - 1][j + 1];else dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j + 1];dp[i][j] %= mod;}}ll ans = 0;int st = 0;if(Min < 0) st = -Min;for (int i = st; i <= diff; ++i) {for (int j = st; j <= i; ++j) {ans = (ans + dp[i][j] * dp[n - i - m][j + tmp] % mod) % mod;//printf("i = %d j = %d ans = %lldn", i, j, ans);}}printf("%I64dn", ans);}return 0;
}
本文发布于:2024-02-04 05:05:28,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170699723452318.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |