Description
最近11对战平台非常火热,身为dota爱好者的FZ当然也不能落后,得赶紧把积分刷上去才行。现在FZ 要打n局,他想玩m个英雄(m个英雄必须至少玩1次),当然一直玩同一个英雄是件无聊的事,所以如果FZ在玩两个相同英雄之间必须至少打了k个其他的英雄。现在问FZ有多少种方案来打dota?最后答案可能会很大,输出%1000000007即10^9+7就行了。
Input
输入第一行为整数T,T<=10 表示有T组测试数据
接下来T行,每一行三个整数n,m,k (1<=m<=n<=1000,0<=k<=1000)
Output
对于每组数据输出一行,总的方案数%1000000007的值
Sample Input
3
3 2 1
4 2 2
4 3 2
Sample Output
2
0
6
解题思路:
1.递推
Dp[i][j]=dp[i-1][j-1]*(m-j+1); 。。1
If (j>k) dp[i][j]+=dp[i-1][j]*(j-k) 。。2
Dp[i][j]为前i局用了j个不同的英雄的方法数。。。1 如果第i局用的是此前没有使用过的英雄,第i句有m-j+1个英雄可以选择,。。2 如果第i局用的是此前使用过的英雄,前提条件是使用过的英雄要大于k,否则连续k个英雄中肯定会有相同的,因为他不能使用最近的k个英雄,所以有(j-k)个英雄可以选择
2.容斥原理
#include<iostream>
using namespace std;
const int D = 1000;
const int M = 1000000007;
long long dp[D+1][D+1];
int main()
{
int N;
cin>>N;
while(N--)
{
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;++i)
{
dp[i][0] = 0;
dp[0][i] = 0;
}
dp[0][0] = 1;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
dp[i][j] = dp[i-1][j-1]*(m-j+1);
if(j>k)
dp[i][j] += dp[i-1][j]*(j-k);
dp[i][j] %= M;
}
}
cout<<dp[n][m]<<endl;
}
return 0;
}
最后欢迎大家访问我的个人网站: 1024s