合唱 | ||||||
| ||||||
Description | ||||||
Leyni要组织一场合唱,有x个男生和y个女生要参加,Leyni要将他们排成一行,要求最多可以将a个男生连续排在一起,最多将b个女生连续排在一起。我们假设所有的男生之间是没有区别的,所有的女生之间也是没有区别的,而且这x + y个人都必须参加合唱。 Leyni想知道不同的方案总数除以1000000007的余数。 | ||||||
Input | ||||||
本题有多组测试数据,输入的第一行是一个整数T代表着测试数据的数量,接下来是T组测试数据。 对于每组测试数据: 第1行 包含四个以空格分隔的整数x,y,a,b (1 ≤ x, y ≤ 100, 1 ≤ a, b ≤ 10)。 | ||||||
Output | ||||||
对于每组测试数据: 第1行 输出方案总数除以1000000007的余数。 | ||||||
Sample Input | ||||||
2 2 3 1 2 2 4 1 1 | ||||||
Sample Output | ||||||
5 0 | ||||||
Hint | ||||||
第一组样例的五种方案为:男女男女女,男女女男女,女男女男女,女男女女男,女女男女男。 | ||||||
Source | ||||||
哈理工2012春季校赛热身赛 2012.04.03 | ||||||
Author | ||||||
齐达拉图@HRBUST |
思路:
1、统计方案数,考虑dp,设定dp【i】【j】【2】:
①dp【i】【j】【0】表示长度为i的队列中,以男生结尾,并且一共有j个男生的方案数。
②dp【i】【j】【0】表示长度为i的队列中,以女生结尾,并且一共有j个男生的方案数。
那么ans=dp【n】【x】【0】+dp【n】【x】【1】;
2、其状态转移方程也不是很难写出:
①dp【i】【j】【0】+=dp【i-l】【j-l】【1】;表示在以女生结尾的序列之后,加上连续的l个男生。(1<=l<=a)
②dp【i】【j】【1】+=dp【i-l】【j】【0】;表示在以男生结尾的序列之后,加上连续的l个女生。(1<=l<=b)
3、注意数组不要越界以及取模问题。
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
#define ll long long int
#define mod 1000000007
ll dp[205][105][2];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int x,y,a,b;
scanf("%d%d%d%d",&x,&y,&a,&b);
int n=x+y;
memset(dp,0,sizeof(dp));
dp[0][0][0]=1;
dp[0][0][1]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=x&&j<=i;j++)
{
for(int l=1;l<=a;l++)
{
if(j-l>=0)
dp[i][j][0]+=dp[i-l][j-l][1];
dp[i][j][0]%=mod;
}
for(int l=1;l<=b;l++)
{
if(i-l>=0)
dp[i][j][1]+=dp[i-l][j][0];
dp[i][j][1]%=mod;
}
}
}
ll output=(dp[n][x][0]+dp[n][x][1])%mod;
printf("%lld\n",output);
}
}