[BZOJ3027][Ceoi2004]Sweet(生成函数)
2017-04-25 19:54
393 查看
题目描述
传送门题目大意:有n种糖果,每种mi个,至少吃掉a个,至多b个,求吃掉糖果的方案数。
题解
组合问题,用到普通型生成函数首先设f(i)表示至多吃掉i个的方案数,问题可以转化为求f(b)−f(a−1),求f(i)实际上就是要求生成函数的xi项的系数
首先把生成函数的式子写出来,并化成闭形式
∏in(1+x+x2+...+xmi)=∏in1−xmi+11−x=∏in(1−xmi+1)(1−x)n
然后可以看出多项式变成(1+x+x2+x3...)n∏in(1−xmi+1)
第二个式子展开至多有2n个系数不为0的项,可以爆搜展开的每一项
而对于第一个式子,它的展开式的第i项的系数为Cn−1n+i−1
那么假设现在爆搜到了一项k∗xy,当前要求的是f(a),那么实际上就是要求生成函数第0..a-y项的系数和,也就是k×(Cn−1n−1+Cn−1n+Cn−1n+1+...+Cn−1n+a−y−1)
利用组合数的递推公式Cji=Cj−1i+Cj−1i−1进行化简,系数和为k×Cnn+a−y
因为n比较小,求组合数的时候可以上下相消然后暴力枚举,而模数不是质数有可能不存在逆元,但是模数较小,可以在取模时先乘上n!⋅Mod然后最后再除回去
时间复杂度O(2n⋅n)
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define Mod 2004 int n,a,b,now,ans; int m[15]; long long mul; int C(int n,int m) { if (n<m) return 0; long long ans=1,mod=mul*Mod; for (int i=n-m+1;i<=n;++i) ans=(long long)i%mod*(long long)ans%mod; return (ans/mul)%Mod; } void dfs(int dep,int xi,int mi,int lim) { if (dep==n+1) { now=(now+xi*C(n+lim-mi,n)%Mod)%Mod; return; } dfs(dep+1,xi,mi,lim); dfs(dep+1,-xi,mi+m[dep]+1,lim); } int calc(int lim) { now=0; dfs(1,1,0,lim); return now; } int main() { scanf("%d%d%d",&n,&a,&b); mul=1;for (int i=2;i<=n;++i) mul=mul*i; for (int i=1;i<=n;++i) scanf("%d",&m[i]); ans=calc(b)-calc(a-1);ans=(ans%Mod+Mod)%Mod; printf("%d\n",ans); }
相关文章推荐
- bzoj 3027: [Ceoi2004]Sweet (生成函数)
- [bzoj3027][Ceoi2004]Sweet【生成函数】【组合数】
- 【BZOJ 3027】 3027: [Ceoi2004]Sweet (容斥原理+组合计数)
- [BZOJ3027][Ceoi2004]Sweet 容斥+组合数
- 【BZOJ3027】【CEOI2004】Sweet
- bzoj 3027: [Ceoi2004]Sweet
- bzoj 3027: [Ceoi2004]Sweet(母函数+组合数)
- BZOJ3027 - [CEOI2004]Sweet
- 3027: [Ceoi2004]Sweet
- BZOJ 3027 Sweets 生成函数,容斥
- [CEOI 2004]Sweet
- [BZOJ2684][CEOI2004]锯木厂选址
- 【bzoj3028】食物 数论+生成函数
- BZOJ2004 HNOI2010公交线路(状压dp+矩阵快速幂)
- 【bzoj1212】[HNOI2004]L语言 AC自动机
- BZOJ1027 [HNOI2004]打鼹鼠 【dp】
- BZOJ 1208 [HNOI 2004] 宠物收养所 (splay)
- bzoj 1212 [HNOI2004]L语言
- [JSOI2004]平衡点/[BZOJ3680]吊打XXX
- BZOJ 1367: [Baltic2004]sequence [可并堆 中位数]