zoukankan      html  css  js  c++  java
  • 题解 洛谷 P6078 【[CEOI2004]糖果】

    对于至少 (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} ight)sum_{j geqslant 0} inom{n+j-1}{j} x^j ]

    (f(x))(0) 次到 (i) 次项的系数和即为限制不超过 (i) 个的方案数,第一项可以直接 (dfs),后一项可以用 (inom{n}{m} = inom{n}{m-1} + inom{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;
    }
    
  • 相关阅读:
    希腊字母写法
    The ASP.NET MVC request processing line
    lambda aggregation
    UVA 10763 Foreign Exchange
    UVA 10624 Super Number
    UVA 10041 Vito's Family
    UVA 10340 All in All
    UVA 10026 Shoemaker's Problem
    HDU 3683 Gomoku
    UVA 11210 Chinese Mahjong
  • 原文地址:https://www.cnblogs.com/lhm-/p/13395025.html
Copyright © 2011-2022 走看看