GYM 101147 G.The Galactic Olympics(dp)

来源:互联网 发布:马赛克拼图软件 编辑:程序博客网 时间:2024/04/30 16:21

Description
n场不同的比赛,派k个人去,一个人可以参加多场比赛且至少参加一场,每场比赛只能且必须要有一个人参加,问方案数
Input
第一行一整数T表示用例组数,每组用例输入两个整数n和k分别表示比赛数和人数(1<=k<=1e6,1<=n<=1e3)
Output
输出方案数
Sample Input
1
3 2
Sample Output
6
Solution
k>n时显然无解,k<=n时吗,设dp[i][j]表示i场比赛分配给j个人的方案数
j=1时,dp[i][1]=1
j=i时,dp[i][i]=i!
1 < j < i时,dp[i][j]=j*dp[i-1][j-1]+j*dp[i-1][j],第一部分表示如果前i-1场比赛已经分配给了j-1个人,那么第i场比赛必须分配给第j个人,第j个人有j种情况,所以该部分对dp[i][j]的贡献就是j*dp[i-1][j-1];第二部分表示如果前i-1场比赛已经分配给了j个人,那么第i场比赛随便让这j个人中的一个人参加即可,所以这部分对答案的贡献就是j*dp[i-1][j]
Code

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define INF 0x3f3f3f3f#define maxn 1111const ll mod=1000000007ll;ll dp[maxn][maxn];void init(){    dp[0][0]=1;    for(int i=1;i<=1000;i++)    {        dp[i][1]=1,dp[i][i]=1ll*i*dp[i-1][i-1]%mod;        for(int j=2;j<i;j++)dp[i][j]=1ll*j*(dp[i-1][j-1]+dp[i-1][j])%mod;    }}int main(){    freopen("galactic.in","r",stdin);    init();    int T,n,k;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&k);        if(k>n)printf("0\n");        else printf("%I64d\n",dp[n][k]);    }    return 0;}
0 0
原创粉丝点击