题解 [BZOJ4710] 分特产

题面

解析

step 1

我们先考虑下有人没有的情况吧,

那对于每个特产就是放隔板的情况了,

(a[i])为第(i)个特产的个数,

那么第(i)个特产的方案数就是(C_{a[i]+n-1}^{n-1}),(这个不解释了吧)

然后再根据乘法原理乘起来就行了:(prod_{i=1}^mC_{a[i]+n-1}^{n-1}).

step 2

但是要求每个人都要分到啊.

而上面的式子是包含了有人没有的情况的.

所以我们容斥一下就好了.

(f[k])表示至少有(k)个人没有分到(也就是钦定(k)个人没有),

那么方案数就是(f[k]=prod_{i=1}^mC_{a[i]+n-k-1}^{n-k-1}).

最后来一个容斥:(ans=sum_{k=0}^{n-1}(-1)^kC_n^kf[k]),

组合数是因为可以任意钦定(k)个人没有.

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
#define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
using namespace std;

inline int read(){
	int sum=0,f=1;char ch=getchar();
	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
	return f*sum;
}

const int N=2001;
const int Mod=1000000007;
int n,m,a[N];
ll c[N][N];
ll f[N],ans;

int main(){
	n=read();m=read();
	for(int i=0;i<N;i++) c[i][0]=1;
	for(int i=1;i<N;i++)		
		for(int j=1;j<N;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%Mod;
	for(int i=1;i<=m;i++) a[i]=read();
	for(int i=0;i<=n;i++) f[i]=1;
	for(int i=0;i<n;i++)
		for(int j=1;j<=m;j++) f[i]=(f[i]*c[a[j]+n-i-1][n-i-1])%Mod;	
	for(int i=0;i<n;i++) ans=(ans+c[n][i]*f[i]%Mod*((i&1)? -1:1))%Mod;
	printf("%lld
",(ans+Mod)%Mod);
	return 0;
}

原文地址:https://www.cnblogs.com/zsq259/p/11181856.html