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

题解 P6078 【[CEOI2004] Sweets】

时间:2020-09-16 12:19:21      阅读:26      评论:0      收藏:0      [点我收藏+]

标签:its   注意   evo   解题思路   c++   描述   lan   for   har   

题目描述

\(John\)得到了\(n\)罐糖果。不同的糖果罐,糖果的种类不同(即同一个糖果罐里的糖果种类是相同的,不同的糖果罐里的糖果的种类是不同的)。第\(i\)个糖果罐里有\(m_{i}\)个糖果。\(John\) 决定吃掉一些糖果,他想吃掉至少\(a\)个糖果,但不超过\(b\)个。问题是 \(John\)无法确定吃多少个糖果和每种糖果各吃几个。有多少种方法可以做这件事呢?

解题思路

生成函数题,考虑对于第\(i\)堆吃\(j\)个糖果的方案并写成封闭模式为

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

那么对于吃\(i\)个的方案数为

\[G(x)=\prod_{i=1}^n F_i(x)=(1-x)^{-n}\prod_{i=1}^n(1-x^{m_i+1}) \]

对于\((1-x)^{-n}\)我们使用牛顿广义二项式展开可得\(\begin{aligned}(1-x)^{-n}=\sum_{k=0}^{\infty}\dbinom{-n}{k}(-x)^k=\sum_{k=0}^{\infty}(-1)^k\dbinom{n+k-1}{k}(-x)^k=\sum_{k=0}^{\infty}\dbinom{n+k-1}{k}x^k\end{aligned}\)

对于后面的柿子我们直接暴搜,怎么暴力怎么来就可以,对于前面的\(\begin{aligned}\sum_{k=0}^{\infty}\dbinom{n+k-1}{k}x^k\end{aligned}\),我们考虑对答案的贡献,对于答案是\(x^a\)~\(x^b\)对应的系数,则设\(\prod_{i=1}^n(1-x^{m_i+1})\)枚举到了\(x^k\),则为\(\begin{aligned}\sum_{i=a-k}^{b-k}\dbinom{n+i-1}{i}\end{aligned}\),展开后对其用加法公式\(\dbinom{n}{m}=\dbinom{n-1}{m}+\dbinom{n-1}{m-1}\)进行化简可得为\(\dbinom{n+b-k}{b-k}-\dbinom{n+a-k-1}{a-k-1}\),然后就可以做了,总体时间复杂度为\(O(2^n)\)

细节注意

模数不是质数,组合数用定义进行计算

\(Code\)

#include<bits/stdc++.h>
    
#define LL long long
    
#define _ 0
    
using namespace std;
    
/*Grievous Lady*/
    
template <typename _n_> void mian(_n_ & _x_){
    _x_ = 0;int _m_ = 1;char buf_ = getchar();
    while(buf_ < ‘0‘ || buf_ > ‘9‘){if(buf_ == ‘-‘)_m_ =- 1;buf_ = getchar();}
    do{_x_ = _x_ * 10 + buf_ - ‘0‘;buf_ = getchar();}while(buf_ >= ‘0‘ && buf_ <= ‘9‘);_x_ *= _m_;
}
    
const int kato = 20;

LL fac = 1 , ans , n , a , b , m[kato];

#define mod 2004

inline int c(int a , int b){
    if(a < b) return 0;
    LL res = 1 , tmp = fac * mod;
    for(int i = a - b + 1;i <= a;i ++){
        res = res * i % tmp;
    }
    return (res / fac) % mod;
}

void dfs(int x , int opt , int t){
    if(x == n + 1){
        ans = (ans + opt * (c(n + b - t , n) - c(n + a - t - 1 , n))) % mod;
        return;
    }
    dfs(x + 1 , opt , t) , dfs(x + 1 , - opt , t + m[x] + 1);
}

inline int Ame_(){
    mian(n) , mian(a) , mian(b);
    for(int i = 1;i <= n;i ++){
        mian(m[i]);
        fac = fac * i;
    }
    dfs(1 , 1 , 0);
    if(ans < 0) ans += mod;
    printf("%lld\n" , ans);
    return ~~(0^_^0);
}
    
int Ame__ = Ame_();
    
int main(){;}

/*
2 1 3
3
5
*/

-----\(\mathcal{Ame\_\_}\)

题解 P6078 【[CEOI2004] Sweets】

标签:its   注意   evo   解题思路   c++   描述   lan   for   har   

原文地址:https://www.cnblogs.com/Ame-sora/p/13603968.html

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