派队方案
时间限制:1000 ms | 内存限制:65535 KB
难度:3
输入
多组测试数据。每组测试数据占一行,每行两个数字n(1<=n<=100),m(1<=m<=100)表示有n场比赛,m支集训队。其中输入数据保证n>=m。
输出
每组输入数据的输出占一行,结果对1000000007取余。
样例输入
3 2
5 4
样例输出
6
240
描述
2017年有n场ACM比赛,南阳理工学院有m支集训队,且这n场比赛学校均会派一个队伍参赛。现在赵老师来安排外出比赛顺序,他想知道如果要使每个队伍至少外出比赛一次,则有多少种派队方案?(保证这n场比赛时间相互独立)
思路:
dp[i]表示n轮比赛,有i个队参与,有多少方案。
如果没有每个队至少外出比赛一次的限制条件,很容易得出dp[i]=pow(i,n);
加上限制条件,可以容斥一下。 。大概就是扣除从m个人里面选取j个人的方案数。取模注意一下。
代码:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 2000005
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
int n,m;
ll dp[105],C[105][105];
ll Pow(int a,int b)
{
ll res=1,p=a;
while(b)
{
if(b&1) res=res*p%(mod<<1);
p=p*p%(mod<<1);
b>>=1;
}
return res;
}
int main()
{
memset(C,0,sizeof C);
C[0][0]=1;
for(int i=1;i<=100;i++)
{
C[i][0]=1;
for(int j=1;j<=i;j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
while(~scanf("%d%d",&n,&m))
{
dp[1]=1;
for(int i=2;i<=m;i++)
{
ll s=0;
for(int j=1;j<i;j++)
{
s=(s+C[i][j]*dp[j]%mod)%mod;
}
dp[i]=(Pow(i,n)-s)%mod;
if(dp[i]<0)
while(dp[i]<0) dp[i]+=mod;
}
printf("%lld\n",dp[m]);
}
return 0;
}
/*
1
13 9
2 -6 -3 -3 0 1 9 0 -4 -4 1 -4 6
4 1 -3 -5 9 4 1 -1 0 6 -9 -3 -2
*/