题意:
有(n+m)个A,B,求子序列有n个AB,m个BA 的方案数
题解
贪心分析(找规律): 因为要匹配n个AB那么 匹配AB的A 当然越靠前越好
同理匹配BA的B当然越靠前越好,也就是假设有x,y个A,B把A全部当成AB(前半部分)凑
把B全部当成BA(前半部分凑),当A满足n个时,多出的最后一个必然用来凑BA也就是说
当前必须有1个B,B同理,任意时刻假设A的数量x,B的数量y,则x<=n+y,y<=m+x
时刻最多也就2*(n+m),dp计数,长度从0开始.
1.组合数学
C(2n+2m,n+m) 总方案 2n+2m个位置中 抽 n+m个给A
不符合的方案 也就是 任意时刻不符合 (x-n<=y,y<=m+x) 的方案
卡特兰数 (刚好不满足直线 两条)
l1: y = x + m + 1 关于点(2n,2m)对称 (m-1,2n+m+1)
l2: y = x - n - 1 关于点(2n,2m)对称 (2m+n+1,n-1)
方案(l1) C(2n+2m,m-1)
方案(l2) C(2n+2m,n-1)
2.dp计数
观察最终答案一定是n+m个A,n+m个B,在求的过程中满足约束即可
if (i + 1 <= n + j) dp[i+1][j] += dp[i][j]
if (j + 1 <= m + i) dp[i][j+1] += dp[i][j]
code:
#include <bits/stdc++.h>
using namespace std;
int dp[2010][2010],n,m;
const int mod = 1e9 + 7;
int main() {
while (scanf("%d%d",&n,&m) == 2) {
for (int i = 0; i <= n+m; ++i)
for (int j = 0; j <= n+m; ++j)
dp[i][j] = 0;
dp[0][0] = 1;
for (int i = 0; i <= n+m; ++i) {
for (int j = 0; j <= n+m; ++j) {
if (i + 1 <= n + j) dp[i+1][j] = (dp[i+1][j] + dp[i][j]) % mod;
if (j + 1 <= m + i) dp[i][j+1] = (dp[i][j+1] + dp[i][j]) % mod;
}
}
printf("%d\n",dp[n+m][n+m]);
}
return 0;
}