XDOJ1186 - FZ打11

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值