arc110 D - Binomial Coefficient is Fun
题意:
给定长为 \(n\) 的非负整数组 \(a[]\)
\(b[]\) 为元素任取但元素和不大于给定值 \(M\) 的非负整数组
对 \(b[]\) 的某种取值定义 \(f(b[])=\prod\limits_{i=1}^n C_{b_i}^{a_i}\)。求 \(\sum\limits_{b[]} f(b[])\)
\(n\le 2000, 1\le M\le 1e9, 0\le a_i\le 2000\)
思路:
从 \(M\) 个球中取 \(b_i\) 个,再从这 \(b_i\) 中取 \(a_i\) 个(\(i=1\sim n\))的方案数。
如果直接从 \(M\) 个球中取 \(\sum a_i\) 个,\(a_i\) 就全混在一起没有分开,怎么把 \(a_i\) 分开?
把小球从左到右编号,同时考虑有 \(n\) 块隔板。选出的球中的第一个作为隔板,接下来的 \(a_i\) 个代表 \(a_i\),再下一个代表隔板,再接下来的 \(a_2\) 个代表 \(a_2\)
这样一来,选出的球(除隔板外)就表示出了数组 \(a[]\),而隔板在原来的所有球(包括选出的和未被选的)就决定了数组 \(b[]\)
究竟需要多少块隔板?
如果我们只选 \(n-1\) 块隔板,那么 \(\sum b_i=M\),而实际上 \(\sum b_i\) 可以小于 \(M\);
如果选 \(n+1\) 块隔板即首尾都有隔板,那么显然可以想到重复计数的情况,比如所有 \(n=1\),在左右都放隔板的话选出很多相等的 \(b_1\);
实际上需要 \(n\) 块隔板,假设最后一块隔板为小球 \(id\),把编号为 \([id,end]\) 的球全部舍弃,然后在 \([1,id-1]\) 中选 \(n-1\) 块隔板即可。上述最后一块隔板实际上决定了 \(\sum b_i\)
所以原问题可看成从 \(M+n\) 个球中取 \(n+\sum a_i\) 个球的方案数,答案就是 \(C_{n+M}^{n+\sum a_i}\)
ps. 这个组合数上面比较小,直接按定义算就行了。复杂度 \(O(n+\sum a_i)=O(na_i)\)
ll C(ll n, ll m) {
ll ans = 1;
for(int i = 1; i <= m; i++) (ans *= i) %= mod; // m!
ans = qmi(ans, mod-2); // (m!)^{-1}
for(int i = 0; i < m; i++) (ans *= n - i) %= mod;
return ans;
}
void sol() {
ll n, M, sum = 0; cin >> n >> M;
for(int i = 1, x; i <= n; i++) cin >> x, sum += x;
cout << C(n + M, n + sum);
}

浙公网安备 33010602011771号