牛客2019多校 第一场 ABBA

牛客多校 第一场 ABBA

题意:

有(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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值