题意
JYY 带队参加了若干场ACM/ICPC 比赛,带回了许多土特产,要分给实验室的同学们。JYY 想知道,把这些特产分给N 个同学,一共有多少种不同的分法?当然,JYY 不希望任何一个同学因为没有拿到特产而感到失落,所以每个同学都必须至少分得一个特产。例如,JYY 带来了2 袋麻花和1 袋包子,分给A 和B 两位同学,那么共有4 种不同的分配方法:
A:麻花,B:麻花、包子
A:麻花、麻花,B:包子
A:包子,B:麻花、麻花
A:麻花、包子,B:麻花
N, M 不超过1000,每一种特产的数量不超过1000
答案模1e9+7。
分析
只要用全部方案-至少有一个人没有特产的方案+至少有两个人没有特产的方案。。。即可
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=2005;
const int MOD=1000000007;
int n,m,a[N],ny[N],jc[N];
int ksm(int x,int y)
{
int ans=1;
while (y)
{
if (y&1) ans=(LL)ans*x%MOD;
x=(LL)x*x%MOD;y>>=1;
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d",&a[i]);
ny[0]=jc[0]=1;
for (int i=1;i<=2000;i++) jc[i]=(LL)jc[i-1]*i%MOD,ny[i]=ksm(jc[i],MOD-2);
int ans=0;
for (int i=0;i<=n-1;i++)
{
int w=(LL)jc[n]*ny[i]%MOD*ny[n-i]%MOD;
for (int j=1;j<=m;j++) w=(LL)w*jc[n-i+a[j]-1]%MOD*ny[n-i-1]%MOD*ny[a[j]]%MOD;
if (i%2==0) (ans+=w)%=MOD;
else (ans-=w)%=MOD;
}
printf("%d",(ans+MOD)%MOD);
return 0;
}