• CodeForces-451E:Devu and Flowers (母函数+组合数+Lucas定理)


    Devu wants to decorate his garden with flowers. He has purchased n boxes, where the i-th box contains fi flowers. All flowers in a single box are of the same color (hence they are indistinguishable). Also, no two boxes have flowers of the same color.

    Now Devu wants to select exactly s flowers from the boxes to decorate his garden. Devu would like to know, in how many different ways can he select the flowers from each box? Since this number may be very large, he asks you to find the number modulo (109 + 7).

    Devu considers two ways different if there is at least one box from which different number of flowers are selected in these two ways.

    Input

    The first line of input contains two space-separated integers n and s (1 ≤ n ≤ 20, 0 ≤ s ≤ 1014).

    The second line contains n space-separated integers f1, f2, ... fn (0 ≤ fi ≤ 1012).

    Output

    Output a single integer — the number of ways in which Devu can select the flowers modulo (109 + 7).

    Example

    Input
    2 3
    1 3
    Output
    2
    Input
    2 4
    2 2
    Output
    1
    Input
    3 5
    1 3 2
    Output
    3

    题意:给定N种花,每种花有Fi朵,现在要取M朵花,问有多少种方案。

    思路:母函数或者容斥定理,当然,学过数学竞赛的应该知道结论,怎么用容斥定理去做。我更倾向于用母函数去做,虽然方程是一样的,但是感觉后者好理解一些。

    母函数 :    (1+X^1...+X^f1)*(1+X^1...+Xf2)*...(1+X^1...+X^fn)

                    =(1-X^(f1+1))*(1-X^(f2+1))...(1-X^(fn+1)) / ((1-X)^N)

                    =(1-X^(f1+1))*(1-X^(f2+1))...(1-X^(fn+1)) * ((1+X^1+X^2+...)^N)。

    对于前面部分((1-X^(f1+1))*(1-X^(f2+1))...(1-X^(fn+1)) )可以枚举O(2^N),然后剩余部分,就是组合问题了,假设前面的和为S,那么就要在后面部分(((1+X^1+X^2+...)^N))拿M-S个,然后根据组合公式,C(M-S+N-1,N-1)。

    组合公式那里利用Lucas可以降低复杂度,但是我还是觉得复杂度过不去,O(N * 2^N *Mod *LogMod )可能是数据水了,然后只花了900ms。

    容斥定理:假设没有限制F,则得到ans=C(M+N-1,N-1)。但是有限制后有的会超过Fi,枚举超过的那几个,blabla,大概是这个方向啦,具体的我也没有细究。

    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ll long long
    const int Mod=1e9+7;
    int N; ll M,f[22],ans;
    ll qpow(ll a,ll x)
    {
        ll res=1; a%=Mod;
        while(x){
            if(x&1LL) res=res*a%Mod;
            a=a*a%Mod;
            x>>=1;
        }   return res;
    }
    ll Com(ll a,ll b)
    {
        ll res=1,fm=1,fz=1;
        if(a-b<b) b=a-b;
        for(int i=1;i<=b;i++){
            fm=fm*i%Mod;
            fz=fz*(a-i+1)%Mod;
        }
        res=fz*qpow(fm,Mod-2)%Mod;
        return res;
    }
    ll Lucas(ll a,ll b)
    {
        if(b==0) return 1;
        return Lucas(a/Mod,b/Mod)*Com(a%Mod,b%Mod)%Mod;
    }
    void solve()
    {
        for(int i=0;i<(1<<N);i++){
            ll sig=1,sum=M;
            for(int j=0;j<N;j++){
                if((1<<j)&i) sum-=(f[j]+1),sig*=-1;
            }
            if(sum<0) continue;
            ans=(ans+sig*Lucas(N+sum-1,N-1))%Mod;
        }
    }
    int main()
    {
        scanf("%d%lld",&N,&M);
        for(int i=0;i<N;i++)
            scanf("%lld",&f[i]);//,sum+=f[i];
        solve();
        printf("%lld
    ",(ans%Mod+Mod)%Mod);
        return 0;
    }
  • 相关阅读:
    STL堆算法性能分析与优化方法(GCC4.4.2 stl_heap.h源代码分析与改进方案)
    POJ 1631 Bridging Singnals
    一个用于读unicode文本的迭代器(iterator)
    常用文本压缩算法及实现(To be finshed!)
    volatile语义及线程安全singleton模式探讨
    C++实现的huffman与canonical huffman的压缩解压缩系统,支持基于单词的压缩解压缩
    linux环境下 C++性能测试工具 gprof + kprof + gprof2dot
    多线程统计多个文件的单词数目C++0x多线程使用示例
    python嵌入C++ boost.python如何在C++中调用含有不定长参数tuple变量和关键字参数dict变量的函数
    boost.python入门教程 python 嵌入c++
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8576158.html
Copyright © 2020-2023  润新知