Codeforces Round #343 (Div. 2) C

来源:互联网 发布:网络流行aq是什么意思 编辑:程序博客网 时间:2024/06/06 10:47

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:

the total number of opening brackets is equal to the total number of closing brackets;
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
Note
In the first sample there are four different valid pairs:

p = “(“, q = “))”
p = “()”, q = “)”
p = “”, q = “())”
p = “”, q = “)()”
In the second sample the only way to obtain a desired string is choose empty p and q.

In the third sample there is no way to get a valid sequence of brackets.

这个题看着题干能想想到这么一点
因为是括号匹配问题
所以要换成值来求
左括号是1有括号是-1
中间那一坨直接换成一个和就可以了
然后再两边放
来枚举种类,长度和和
这里要用dp预处理
dp[a][b] 这里的a是长度,b是和
存的就是长度
状态转移的原理也很简单
先预处理和尾b的时候
b可以从b+1和b-1这两种状态转移得到
是打表才看出来的规律…
具体原理…
会了再补

会了…
首先每一种状态都是所有的可能出现的情况
然后就会出现了只要在尾部加一个就够的情况
所以就可以这样递推了

#include <iostream>#include <cmath>#include <cstdio>#include <algorithm>#include <string>using namespace std;long long dp[2220][2220];long long mo = 1e9 + 7;int main(){#define int long long    int n, m;    dp[1][1] = 1;    dp[0][0] = 1;    for (int a = 2;a <= 2000;a++)    {        for (int b = 0;b <= a;b++)        {            if (b == 0)            {                dp[a][b] = dp[a - 1][b + 1]%mo;                continue;            }            dp[a][b] = (dp[a - 1][b - 1] + dp[a - 1][b + 1]) % mo;        }    }    cin >> n >> m;    string q;    cin >> q;    int jsd = 0;    int xx = 0;    for (int a = 0;a < q.size();a++)    {        if (q[a] == '(')jsd++;        else jsd--;        xx = min(jsd, xx);    }    if (jsd == q.size() && jsd >= n / 2)    {        cout << 0 << endl;        return 0;    }    int js = 0;    for (int a = 0;a <= n - m;a++)    {        for (int b = 0;b <= a;b++)        {            if (xx + b >= 0 )            {                js = (js + dp[a][b] * dp[n - m - a][jsd + b]) % mo;            }        }    }    cout << js;}
0 0