D. Neko and Aki's Prank
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
Neko is playing with his toys on the backyard of Aki's house. Aki decided to play a prank on him, by secretly putting catnip into Neko's toys. Unfortunately, he went overboard and put an entire bag of catnip into the toys...
It took Neko an entire day to turn back to normal. Neko reported to Aki that he saw a lot of weird things, including a trie of all correct bracket sequences of length 2n2n.
The definition of correct bracket sequence is as follows:
- The empty sequence is a correct bracket sequence,
- If ss is a correct bracket sequence, then (s)(s) is a correct bracket sequence,
- If ss and tt are a correct bracket sequence, then stst is also a correct bracket sequence.
For example, the strings "(())", "()()" form a correct bracket sequence, while ")(" and "((" not.
Aki then came up with an interesting problem: What is the size of the maximum matching (the largest set of edges such that there are no two edges with a common vertex) in this trie? Since the answer can be quite large, print it modulo 109+7109+7.
Input
The only line contains a single integer nn (1≤n≤10001≤n≤1000).
Output
Print exactly one integer — the size of the maximum matching in the trie. Since the answer can be quite large, print it modulo 109+7109+7.
Examples
input
Copy
1
output
Copy
1
input
Copy
2
output
Copy
3
input
Copy
3
output
Copy
9
Note
The pictures below illustrate tries in the first two examples (for clarity, the round brackets are replaced with angle brackets). The maximum matching is highlighted with blue.
分析:用dp[i][j][k]表示从 剩余i个左括号,j个右括号往下走能得到的max,k=0表示这个点与父节点的边不选,1表示要选。
当i==j时,只能选用左括号,
dp[i][j][0]=dp[i-1][j][1]+1
dp[i][j][1]=dp[i-1][j][0]
j>i时,两边都可以选,
dp[i][j][0] = 1 + dp[i - 1][j][1] + dp[i][j - 1][0] //选左右答案是一样的,我有一个绝妙的证明方法,但是这里太小写不下
dp[i][j][1] = dp[i - 1][j][0] + dp[i][j - 1][0]
因为根节点没有父节点,所以最后dp[n][n][0]就是答案(其实这里dp[n][n][0]与dp[n][n][1]的值是一样的)。初始化时只需要初始化i=0的情况即可。
#include "bits/stdc++.h"
using namespace std;
int dp[1004][1004][2];
const int mod = 1e9 + 7;
int main() {
int n;
cin >> n;
memset(dp, 0, sizeof(dp));
for (int i = 0; i <= n; ++i) {
dp[0][i][1] = i / 2;
dp[0][i][0] = (i + 1) / 2;
}
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; ++j) {
if (i == j) {
dp[i][j][0] = (dp[i - 1][j][1] + 1) % mod;
dp[i][j][1] = (dp[i - 1][j][0]) % mod;
} else {
dp[i][j][0] = (1 + dp[i - 1][j][1] + dp[i][j - 1][0]) % mod;
dp[i][j][1] = (dp[i - 1][j][0] + dp[i][j - 1][0]) % mod;
}
}
}
printf("%d\n", dp[n][n][0]);
}