【题目链接】
【算法】
考虑求每个人可以不分的方案
那么,对于每件物品,我们把它分成n份,每一份对应分给每一个人,有C(a[i]+n-1,m-1)种方案,而总方案数就是每种
物品方案数的乘积
然后,根据容斥原理,ans = 至少0人没分到特产 - 至少1人没分到特产 + ... - C(m,m) * 没有一人分到
特产
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 2010 const long long P = 1000000007 ; int i,n,m; long long a[MAXN],fac[MAXN],inv[MAXN]; long long ans; inline long long power(long long a,long long n) { long long ans = 1,b = a; while (n > 0) { if (n & 1) ans = (ans * b) % P; b = (b * b) % P; n >>= 1; } return ans; } inline void init() { int i; fac[0] = 1; for (i = 1; i < MAXN; i++) fac[i] = fac[i-1] * i % P; inv[MAXN-1] = power(fac[MAXN-1],P-2); for (i = MAXN - 2; i >= 1; i--) inv[i] = inv[i+1] * (i + 1) % P; inv[0] = 1; } inline long long C(int n,int m) { return fac[n] * inv[n-m] % P * inv[m] % P; } inline long long calc(int x) { int i; long long ans = 1; for (i = 1; i <= m; i++) ans = (ans * C(a[i]+n-x-1,n-x-1)) % P; return ans; } int main() { init(); scanf("%d%d",&n,&m); for (i = 1; i <= m; i++) scanf("%d",&a[i]); for (i = 0; i <= n; i++) { if (i % 2 == 0) ans = (ans + C(n,i) * calc(i)) % P; else ans = (ans - (C(n,i) * calc(i) % P) + P) % P; } printf("%lld ",ans); return 0; }