zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    LeetCode234回文链表
    LeetCode445两数相加II
    LeetCode24两两交换链表中的节点
    LeetCode19删除链表的倒数第N个节点
    LeetCode513找树左下角的值
    LeetCode637二叉树的层平均值
    LeetCode671二叉树中第二小的节点
    LeetCode337打家劫舍III
    LeetCode124二叉树中的最大路径和
    LeetCode687最长同值路径
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8576158.html
Copyright © 2011-2022 走看看