#4051. ABBA

题目描述

序列长 2×(n+m)2\times (n+m)2×(n+m),包含 n+mn+mn+m 个 AAA 和 n+mn+mn+m 个 BBB.

可以将这个序列划分成 n+mn+mn+m 个子序列,nnn 个 ABABAB,mmm 个 BABABA.

例:ABABABABABAB 可划分为 111 个 AB (i={0,3})AB\ (i={0,3})AB (i={0,3}) 与 111 个 BA (i={1,2})BA\ (i={1,2})BA (i={1,2}).

求这样的序列的个数.
输入格式

包含多组数据.

对每组数据:一行, nnn, mmm.
输出格式

对每组数据,输出一行,一个整数,答案 mod 1000000007mod\ 1000000007mod 1000000007
样例
样例输入

1 2
1000 1000
0 0

样例输出

13
436240410
1

数据范围与提示

对 50%50%50% 的数据,n,m≤10n,m\le 10n,m≤10.

对 100%100%100% 的数据,n,m≤103n,m\le 10^3n,m≤103,数据组数 ≤20\le 20≤20.
来源

2019-Nowcoder-multi round1
题解:
首先,贪心来说,前n个A一定对后n个B,同理。
所以我们可以计f[i][j],表示前i个数中有j个A时,只要后面的数变化可以构成有效数列的方案数。
转移方程为

f[i][j]=f[i-1][j]+f[i-1][j-1];

又因为贪心,所以某个状态是否合法需满足
①扣去n个A,剩下的A可以与前面的B相配。
②扣去m个B,剩下的B可以与前面的A相配。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define N 2005
using namespace std;
const long long mod=1000000007;
long long f[N<<1][N],n,m;
int main()
{
	while(scanf("%lld%lld",&n,&m)!=EOF){
	memset(f,0,sizeof(f));
	f[0][0]=1;
	for(int i=1;i<=2*(n+m);i++){
		for(int j=0;j<=min((long long)i,n+m);j++){
			if(j-n>i-j||i-j-m>j)continue;
			f[i][j]=(f[i-1][j]+f[i-1][j-1])%mod;
		}
	}
	printf("%lld\n",f[2*(n+m)][n+m]);
}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值