bzoj 4710 分特产
有 $n$ 个人,$m$ 种物品,每种物品有 $a_i$ 个,求每个人至少分到一个的方案数
$n,m,a_i \leq 2000$
sol:
比上一个题简单一点
还是考虑容斥
每个人至少分到一个 = 随便选 - 至少 1 个人没分到 + 至少 2 个人没分到 - 至少 3 个人没分到 + ...
至少 $i$ 个人没分到就是选出 $i$ 个人分不到,然后对于每种物品,要把它分给剩下的 $(n-i)$ 个人,注意到物品间是相同的,人是不同的,插板就可以了
最后答案是 $\sum\limits_{i=1}^n (-1)^i \times C_{n}^i \times \prod\limits_{j=1}^m C_{a_j+n-i-1}^{n-i-1}$
#include<bits/stdc++.h> #define LL long long using namespace std; inline int read() { int x = 0,f = 1;char ch = getchar(); for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f; for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0'; return x * f; } const int mod = 1000000007,maxn = 1000000 + 50; int n,m,a[maxn]; int fac[maxn],ifac[maxn]; inline int ksm(int x,int t) { int res = 1; while(t) { if(t & 1)res = 1LL * res * x % mod; x = 1LL * x * x % mod; t = t >> 1; }return res; } inline int C(int n,int m) { if(n < 0 || m < 0 || n < m)return 0; return (((1LL * ifac[m] * ifac[n - m]) % mod) * fac[n]) % mod; } int main() { ifac[0] = fac[0] = 1;for(int i=1;i<=maxn-10;i++)fac[i] = (1LL * fac[i - 1] * i) % mod; ifac[maxn - 10] = ksm(fac[maxn - 10],mod - 2);for(int i=maxn-11;~i;i--)ifac[i] = (1LL * ifac[i + 1] * (i + 1)) % mod; //cout<<1LL * ifac[6] * fac[6]<<endl; n = read(),m = read(); for(int i=1;i<=m;i++)a[i] = read(); int ans = 0; for(int i=0;i<n;i++) { int tmp = C(n,i); for(int j=1;j<=m;j++) tmp = 1LL * tmp * C(n - i - 1 + a[j],a[j]) % mod; //cout<<tmp<<endl; (ans += ((i & 1) ? -1 : 1) * tmp) %= mod; } ans = (ans + mod) % mod; cout<<ans<<endl; }