码迷,mamicode.com
首页 > 其他好文 > 详细

题解 题解 P6078 【[CEOI2004]糖果】

时间:2020-07-29 10:26:25      阅读:77      评论:0      收藏:0      [点我收藏+]

标签:计算   bool   lan   class   void   ret   inline   sdi   def   

对于至少 \(a\) 个,不超过 \(b\) 个的限制,可以先求出限制不超过 \(b\) 个的方案数,然后减去限制不超过 \(a-1\) 个的方案数,即为答案。

对第 \(i\) 个糖果罐列出其的生成函数,得:

\[f_i(x)=\sum_{j=0}^{m_i} x^j = \frac{1-x^{m_i+1}}{1-x} \]

将每个糖果罐对应的生成函数都卷积起来,得到考虑所有糖果罐的生成函数:

\[f(x)=\prod_{i=1}^{n} f_i(x) = \frac{\prod_{i=1}^n 1-x^{m_i+1}}{(1-x)^n} = \left(\prod_{i=1}^n 1-x^{m_i+1} \right)\sum_{j \geqslant 0} \binom{n+j-1}{j} x^j \]

\(f(x)\)\(0\) 次到 \(i\) 次项的系数和即为限制不超过 \(i\) 个的方案数,第一项可以直接 \(dfs\),后一项可以用 \(\binom{n}{m} = \binom{n}{m-1} + \binom{n-1}{m-1}\) 来化简。组合数计算时可以扩大模数,然后将计算得出的答案再除回去即可。

总复杂度为 \(O(2^n n)\)

\(code:\)

#include<bits/stdc++.h>
#define maxn 15
#define p 2004
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c==‘-‘)flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
int n,a,b;
int m[maxn];
int C(int n,int m)
{
    if(n<m) return 0;
    ll x=1,y=1,mod=p;
    for(int i=1;i<=m;++i) x*=i,mod*=i;
    for(int i=n-m+1;i<=n;++i) y=y*i%mod;
    return y/x%mod;
}
int dfs(int x,int sum,int type,int tot)
{
    if(x>n) return C(n+tot-sum,n)*type;
    return (dfs(x+1,sum,type,tot)+dfs(x+1,sum+m[x]+1,-type,tot)+p)%p;
}
int main()
{
    read(n),read(a),read(b);
    for(int i=1;i<=n;++i) read(m[i]);
    printf("%d",(dfs(1,0,1,b)-dfs(1,0,1,a-1)+p)%p);
    return 0;
}

题解 题解 P6078 【[CEOI2004]糖果】

标签:计算   bool   lan   class   void   ret   inline   sdi   def   

原文地址:https://www.cnblogs.com/lhm-/p/13395025.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!