[CEOI2004] Sweets

\(\text{Problem}:\)[CEOI2004] Sweets

\(\text{Solution}:\)

要求的是:

\[\sum\limits_{A\leq \sum w_{i}\leq B}\prod\limits_{i=1}^{n}[w_{i}\leq m_{i}] \]

考虑 \([w_{i}\leq m_{i}]\)\(\text{OGF}\),有:

\[\begin{aligned} F_{i}(x)&=\sum\limits_{j=0}^{m_{i}}x^{j}\\ xF_{i}(x)&=\sum\limits_{j=1}^{m_{i}+1}x^{j}\\ F_{i}(x)&=\cfrac{1-x^{m_{i}+1}}{1-x} \end{aligned} \]

带回到原式中,得到答案及其生成函数为:

\[G(x)=\prod\limits_{i=1}^{n}F_{i}(x)=(1-x)^{-n}\prod\limits_{i=1}^{n}(1-x^{m_{i}+1})\\ ans=\sum\limits_{i=A}^{B}[x^{i}]G(x) \]

发现 \(\prod\limits_{i=1}^{n}(1-x^{m_{i}+1})\) 最多只有 \(2^{n}\) 个项的系数不为 \(0\),而 \(n\leq 10\),故可以暴力展开。现在考虑处理 \((1-x)^{-n}\),有:

\[(1-x)^{-n}=\sum\limits_{i=0}^{\infty}\binom{-n}{i}(-x)^{i}=\sum\limits_{i=0}^{\infty}\binom{-n}{i}(-1)^{i}x^{i} \]

引理 \(1\)(广义二项式系数):

\[\binom{n}{k}=\cfrac{n(n-1)\cdot\cdot\cdot (n-k+1)}{k!},n\in\R,k\in\N \]

引理 \(2\)(关于二项式系数的恒等式):

\[\binom{n}{k}=(-1)^{k}\binom{k-n-1}{k} \]

证明:将等号左右两边展开,根据 \(k\) 的奇偶性分类讨论即可。

回到 \((1-x)^{-n}\),由引理 \(2\),得到:

\[\sum\limits_{i=0}^{\infty}\binom{n+i-1}{i}x^{i} \]

枚举 \(\prod\limits_{i=1}^{n}(1-x^{m_{i}+1})\) 的系数非零项,记第 \(k\) 项的系数为 \(h_{k}\),则它对答案的贡献为:

\[h_{k}\sum\limits_{i=A-k}^{B-k}\binom{n+i-1}{i} \]

\(\binom{n}{m}=\binom{n-1}{m}+\binom{n-1}{m-1}\),得到:

\[h_{k}\sum\limits_{i=A-k}^{B-k}\binom{n+i}{i}-\binom{n+i-1}{i-1}=h_{k}\left(\binom{n+B-k}{B-k}-\binom{n+A-k-1}{A-k-1}\right) \]

要计算的组合数是 \(\binom{n+i}{i}\) 的形式,而模数为 \(2004\),不能直接用逆元来求。比较常规的做法是扩展卢卡斯,这里介绍另一种做法。

展开 \(\binom{n+i}{i}\),得到:

\[\cfrac{(n+i)(n+i-1)\cdot\cdot\cdot(i+1)}{n!} \]

\(S=(n+i)(n+i-1)\cdot\cdot\cdot(i+1)=k_{1}(2004\cdot n!)+r,k\in\Z\)\(\dfrac{S}{n!}≡X\text{ (mod 2004)}\),有:

\[\begin{aligned} \cfrac{S}{n!}&=2004\cdot k_{2}+X\\ k_{1}(2004\cdot n!)+r&=(2004\cdot k_{2}+X)\cdot n!\\ r&=(2004\cdot n!)(k_{2}-k_{1})+X\cdot n!\\ \cfrac{r}{n!}&=2004(k_{2}-k_{1})+X\\ \cfrac{r}{n!}&≡X\text{ (mod 2004)} \end{aligned} \]

而又有 \(S≡r\text{ (mod (2004}\cdot n!))\),所以计算 \(S\) 时对 \((2004\cdot n!)\) 取模得到 \(r\),除以 \(n!\) 再对 \(2004\) 取模就求出了组合数。

总时间复杂度 \(O(n2^{n})\)

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=15;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int n,A,B,a[N],ans,fac;
inline int C(int x,int y)
{
	int res=1;
	for(ri int i=x-y+1;i<=x;i++) res=res*i%(fac*2004);
	return (res/fac)%2004;
}
void DFS(int x,int xs,int cs,int goal)
{
	if(cs>goal) return;
	if(x==n+1)
	{
		ans=(ans+xs*C(n+goal-cs,n)%2004+2004)%2004;
		return;
	}
	DFS(x+1,xs,cs,goal);
	DFS(x+1,-xs,cs+a[x]+1,goal);
}
int Solve(int goal)
{
	ans=0;
	DFS(1,1,0,goal);
	return ans;
}
signed main()
{
	n=read(), A=read(), B=read();
	for(ri int i=1;i<=n;i++) a[i]=read();
	fac=1;
	for(ri int i=1;i<=n;i++) fac*=i;
	printf("%lld\n",(Solve(B)-Solve(A-1)+2004)%2004);
	return 0;
}
posted @ 2021-04-15 21:34  zkdxl  阅读(86)  评论(0编辑  收藏  举报