设计状态fi为分给i个同学,使得每个同学都可以拿到特产的方案数
gi为分给i个同学,至多i个同学都拿到的方案数
设特产数量分别为a1,a2,...,am
gn=∏i=1m(n+ai−1ai−1)
gn=∑i=1nfi ∗ (ni) 反演得到: fn=∑i=1n(−1)n−i ∗ (ni) ∗ ∏j=1m(i+aj−1aj−1)
Code:
#include<bits/stdc++.h>
using namespace std;
long long n, m;
long long a[10010];
const long long mod = 1e9 + 7;
long long jc[10010], inv[10010];
long long quickpow(long long x, long long power) {
long long sum = 1;
while (power) {
if (power & 1)sum *= x;
sum%=mod;x*=x;x%=mod;power/=2;
}
return sum;
}
void init() {
jc[1] = 1;
for (long long i = 2; i <= n; i++) {
jc[i] = jc[i - 1] * i;
jc[i] %= mod;
}
inv[n]=quickpow(jc[n],mod-2);
for(long long i=n-1;i>=1;i--){
inv[i]=inv[i+1]*(i+1);
inv[i]%=mod;
}
return;
}
long long c(long long big,long long sma){
if(sma==0||big==sma)return 1;
return jc[big]*inv[big-sma]%mod*inv[sma]%mod;
}
signed main() {
cin>>n>>m;
for(long long i=1;i<=m;i++)cin>>a[i];
init();
long long ans=0;
for(long long i=1;i<=n;i++){
long long f=((n-i)&1?-1:1);
long long z=c(n,i);
long long sum=1;
for(long long j=1;j<=m;j++){
sum*=c(i+a[j]-1,a[j]-1);
sum%=mod;
}
ans+=f*(z*sum%mod);
ans=(ans+mod)%mod;
}
cout<<ans;
}