[CEOI2004] Sweets

Statement


statement

Solution


考虑对每堆构造其生成函数:

\[F_i(x)=\sum\limits_{j=0}^{m_i}x^j \]

\[xF_i(x)+1-x^{m_i+1}=F_i(x) \]

\[F_i(x)=\dfrac{1-x^{m_i+1}}{1-x} \]

总共取\(i\)个的生成函数就是;

\[G(x)=\prod\limits_{i=1}^nF_i(x)=(1-x)^{-n}\prod\limits_{i=1}^n(1-x^{m_i+1}) \]

答案即为:

\[\sum\limits_{i=a}^b[x^i]G(x) \]

根据牛顿二项式定理可知:

\[(1-x)^{-n}=\sum\limits_{i=0}^n\dbinom{-n}{i}(-x)^i=\sum\limits_{i=0}^n\dfrac{(-n)^{\underline{i}}}{i!}(-x)^i=\sum\limits_{i=0}^n\dbinom{n+i-1}{i}x^i \]

因此

\[G(x)=\left[\sum\limits_{i=0}^n\dbinom{n+i-1}{i}x^i\right]\cdot\prod_{i=1}^n(1-x^{m_i+1}) \]

因为\(n\leq10\),所以可以对\(\prod(1-x^{m_i+1})\)暴力展开,求得\(x^k\)的系数为\(c_k\)。考虑每个\(k\)对答案的贡献:

\[c_k\sum\limits_{i=a-k}^{b-k}\dbinom{n+i-1}{i}=c^k\sum\limits_{i=a-k}^{b-k}\left[\dbinom{n+i}{i}-\dbinom{n+i-1}{i-1}\right] \]

\[=c^k\left[\dbinom{n+b-k}{b-k}-\dbinom{n+a-k-1}{a-k-1}\right]=c^k\left[\dbinom{n+b-k}{n}-\dbinom{n+a-k-1}{n}\right] \]

时间复杂度为\(\mathcal O(n2^n)\)

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 15;
const unsigned int P = 2004;
int A[MAXN];
int n, limL, limR, fac = 1, ans;

inline int binom(int a, int b) {
	if (a < b)
		return 0;
	static const unsigned long long MOD = 1ll * P * fac;
	long long res = 1;
	for (int i = a - b + 1;i <= a; ++i)
		res = res * i % MOD;
	return (res / fac) % P;
}

void getAns(int id, int o, int k) {
	if (id == n + 1)
		return ans = (1ll * ans + (o * (binom(n + limR - k, n) - binom(n + limL - k - 1, n)) + P) % P + P) % P, void();
	getAns(id + 1, o, k), getAns(id + 1, -o, k + 1 + A[id]);
}

int main(void) {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	
	cin >> n >> limL >> limR;
	for (int i = 1;i <= n; ++i)
		cin >> A[i], fac *= i;
	getAns(1, 1, 0),
	cout << ans << '\n';
	
	return 0;
}
posted @ 2021-02-18 11:25  Beginner2670  阅读(67)  评论(0)    收藏  举报