Codeforces Round #343 (Div. 2)-C. Famil Door and Brackets

原题链接

C. Famil Door and Brackets
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

As Famil Door’s birthday is coming, some of his friends (like Gabi) decided to buy a present for him. His friends are going to buy a string consisted of round brackets since Famil Door loves string of brackets of length n more than any other strings!

The sequence of round brackets is called valid if and only if:

  1. the total number of opening brackets is equal to the total number of closing brackets;
  2. for any prefix of the sequence, the number of opening brackets is greater or equal than the number of closing brackets.

Gabi bought a string s of length m (m ≤ n) and want to complete it to obtain a valid sequence of brackets of length n. He is going to pick some strings p and q consisting of round brackets and merge them in a string p + s + q, that is add the string p at the beginning of the string s and string q at the end of the string s.

Now he wonders, how many pairs of strings p and q exists, such that the string p + s + q is a valid sequence of round brackets. As this number may be pretty large, he wants to calculate it modulo 109 + 7.

Input

First line contains n and m (1 ≤ m ≤ n ≤ 100 000, n - m ≤ 2000) — the desired length of the string and the length of the string bought by Gabi, respectively.

The second line contains string s of length m consisting of characters '(' and ')' only.

Output

Print the number of pairs of string p and q such that p + s + q is a valid sequence of round brackets modulo 109 + 7.

Examples
input
4 1
(
output
4
input
4 4
(())
output
1
input
4 3
(((
output
0

dp[i][j]表示长度为i括号序列中, 左括号比右括号多j的序列数量.dp[i][j] = dp[i-1][j+1] + dp[i-1][j-1]

#include <bits/stdc++.h>
#define maxn 2005
#define MOD 1000000007
using namespace std;
typedef long long ll;

ll dp[maxn][maxn];
char str[100005];
int n, m;
void Init(){
	
	dp[0][0] = 1;
	int d = n - m;
	for(int i = 1; i <= d; 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] % MOD;
	 }
}
int main(){
	
//	freopen("in.txt", "r", stdin);
	scanf("%d%d%s", &n, &m, str);
	Init();
	int sum = 0, mins = 1e9;
	for(int i = 0; str[i]; i++){
		if(str[i] == '(')
		 sum++;
		else
		 sum--;
		mins = min(sum, mins);
	}
	int d = n - m;
	ll ans = 0;
	for(int i = 0; i <= d; i++)
	 for(int j = 0; j <= i; j++){
	 	if(j + mins < 0 || sum + j > d)
	 	 continue;
	 	ans += dp[i][j] % MOD * (dp[d-i][sum+j] % MOD);
	 	ans %= MOD;
	 }
	printf("%I64d\n", ans);
	
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值