Description
n场不同的比赛,派k个人去,一个人可以参加多场比赛且至少参加一场,每场比赛只能且必须要有一个人参加,问方案数
Input
第一行一整数T表示用例组数,每组用例输入两个整数n和k分别表示比赛数和人数(1<=k<=1e6,1<=n<=1e3)
Output
输出方案数
Sample Input
1
3 2
Sample Output
6
总结:
做这一类求方案数的题时,不要总想着用组合数一个表达式就算出来,会重复计算啥的=-=
组合数学做不出来,换一种思路,用dp。
题解
dp[i][j],i为场数,j为人数,dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1]*j。前一项是前i-1场比赛有j个人参加,第i场比赛从j个人中任选一个人出来。
后一项是前i-1场比赛有j-1人参加,第i场比赛分配给第j个人,而第j个人有j种情况。
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 1e9+7; const int N = 1e3+20; #define dep(i,a,b) for(int i=(a);i>=(b);i--) #define rep(i,a,b) for(int i=(a);i<=(b);i++) int n,k,t;ll dp[N][N]; int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>t; dp[0][0]=1; rep(i,1,1e3) rep(j,1,1e3) dp[i][j]=(dp[i-1][j]*j+dp[i-1][j-1]*j)%mod; while(t--){ cin>>n>>k; if(n<k) cout<<0<<endl; else cout<<dp[n][k]<<endl; } return 0; }