文章目录

题目链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=4710

题意:m种物品,每种 <math> <semantics> <mrow> <msub> <mi> a </mi> <mi> i </mi> </msub> </mrow> <annotation encoding="application&#47;x&#45;tex"> a_i </annotation> </semantics> </math>ai个,分给n个人,每人至少一个,问几种分法?
又是一道感觉很懵逼的容斥题

如果就只有一种土特产的话就是灰常标准的隔板法了,但是现在是m种怎么办呢?
直接来凑就要这种分给那几个人,下一种又分给那些还没得到的人。。。。这样凑要凑成最后每个人都至少分到一个。如果没有每人至少一个的条件,又比较好办,那就直接每种特产拿去分,用至少0个那种隔板法,然后把每次的分的方法数乘起来就行了。

但现在就是加了这个每人至少一个的条件怎么办呢?

又是容斥。。。
枚举多少个人没有分到,奇数个人没有分到就减,偶数个就加
为啥这样就阔以了喃?感觉不能完全理解啊

#include"bits/stdc++.h"
#define out(x) cout<<#x<<"="<<x
#define C(n,m) (m>n||n<0?0:(long long)fac[(n)]*invf[(m)]%MOD*invf[(n)-(m)]%MOD)
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int MOD=1e9+7;
int N,M;
int a[maxn];
LL ksm(LL a,LL b,LL mod)
{
	LL res=1,base=a;
	while(b)
	{
		if(b&1)res=(res*base)%mod;
		base=(base*base)%mod;
		b>>=1;
	}
	return res;
}
LL fac[maxn]={1,1},invf[maxn]={1,1};
void InitFac(int n)
{
	for(int i=2; i<=n; i++)fac[i]=fac[i-1]*i%MOD;
	invf[n]=ksm(fac[n],MOD-2,MOD);
	for(int i=n-1; i>=2; i--)invf[i]= invf[i+1]*(i+1)%MOD;
}
LL geban0(int n,int x)//隔板法x个物品分给n个人,每人至少0个 
{
	return C(x-1+n,n-1);
}

LL given(int n)//m种特产分别分给n个人,用乘法 
{
	LL res=1;
	for(int i=1;i<=M;i++)res=res*geban0(n,a[i])%MOD;
	return res;
}

int main()
{
	InitFac(maxn-5);
	while(cin>>N>>M)
	{
		for(int i=1;i<=M;i++)cin>>a[i];
		LL res=0;
		for(int i=0;i<=N;i++)//i个人没有分到 
		{
			LL tp=C(N,i)*given(N-i);
			if(i%2)res-=tp;
			else res+=tp;
			res%=MOD;
		}
		res=(res+MOD)%MOD;
		cout<<res<<endl;
	}
}