zoukankan      html  css  js  c++  java
  • CF451E Devu and Flowers

    题目描述:

    Devu想用花去装饰他的花园,他已经购买了n个箱子,第i个箱子有fi朵花,在同一个的箱子里的所有花是同种颜色的(所以它们没有任何其他特 征)。另外,不存在两个箱子中的花是相同颜色的。 现在Devu想从这些箱子里选择s朵花去装饰他的花园,Devu想要知道,总共有多少种方式从这些箱子里取出这么多的花?因为结果有可能会很大,结果需要 对1000000007取模。 Devu认为至少有一个箱子中选择的花的数量不同才是两种不同的方案。

    题解:

    乍一看很难,但是化成容斥将会非常好做。

    由于n极小,所以可以枚举每一篮子花是否超出当前fi,然后通过容斥有:

    ans = g0 - g1 + g2 - g3 + g4 - g5 +……

    其中gi表示有i个篮子超限时方式总数。

    一定要多取余:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define MOD 1000000007
    ll n;
    ll s,a[25],ans;
    ll fast(ll x,int y)
    {
        ll ret = 1ll;
        while(y)
        {
            if(y&1)ret=ret*x%MOD;
            x=x*x%MOD;
            y>>=1;
        }
        return ret;
    }
    ll C(ll x,ll y)
    {
        ll sx=1ll,sy=1ll;
        for(ll i=1ll;i<=y;i++)
        {
            sx=(sx*(x%MOD-i%MOD+1ll)%MOD+MOD)%MOD;
            sy=sy*(i%MOD)%MOD;
        }
        return (fast(sy,MOD-2)*sx%MOD+MOD)%MOD;
    }
    int main()
    {
        scanf("%lld%lld",&n,&s);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        for(int i=0;i<(1<<n);i++)
        {
            ll f=1ll,g=s;
            for(int j=0;j<n;j++)
            {
                if(i&(1<<j))
                {
                    g-=a[j+1]+1ll;
                    f*=-1;
                }
            }
            if(g<0)continue;
            ans=((ans+f*C(g+n-1ll,n-1ll)%MOD)%MOD+MOD)%MOD;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    5.5,5.6
    5.1,5.2
    第四章.编程练习
    多源最短路径--flody算法
    Java 面试题
    python 打包exe程序
    sql优化
    二叉树
    todo: 队列、栈、散列集
    java注解
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9897763.html
Copyright © 2011-2022 走看看