题目描述
序列长 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;
}