Codeforces 451E Devu and Flowers(容斥原理)

Codeforces 451E Devu and Flowers(容斥原理)

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

题目链接:Codeforces 451E Devu and Flowers

题目大意:有n个花坛。要选s支花,每一个花坛有f[i]支花。同一个花坛的花颜色同样,不同花坛的花颜色不同,问说能够有多少种组合。

解题思路:2n的状态,枚举说那些花坛的花取超过了,剩下的用C(n1sum+n1)隔板法计算个数。注意奇数的位置要用减的。偶数的位置用加的。容斥原理。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;
typedef long long ll;

//ll n, m, p;

ll qPow (ll a, ll k, ll p) {
    ll ans = 1;

    while (k) {
        if (k&1)
            ans = (ans * a) % p;
        a = (a * a) % p;
        k /= 2;
    }
    return ans;
}

ll C (ll a, ll b, ll p) {

    if (a < b)
        return 0;

    if (b > a - b)
        b = a - b;

    ll up = 1, down = 1;

    for (ll i = 0; i < b; i++) {
        up = up * (a-i) % p;
        down = down * (i+1) % p;
    }
    return up * qPow(down, p-2, p) % p; // 逆元
}

ll lucas (ll a, ll b, ll p) {
    if (b == 0)
        return 1;
    return C(a%p, b%p, p) * lucas(a/p, b/p, p) % p;
}

const int maxn = 25;
const ll mod = 1e9+7;
int n;
ll s, f[maxn];

ll solve () {
    ll ans = 0;
    for (int i = 0; i < (1<<n); i++) {
        ll sign = 1, sum = s;
        for (int j = 0; j < n; j++) {
            if (i&(1<<j)) {
                sum -= (f[j]+1);
                sign *= -1;
            }
        }

        if (sum < 0)
            continue;
        ans += sign * lucas(sum + n - 1, n - 1, mod);
        ans %= mod;
    }
    return (ans + mod) % mod;
}

int main () {
    scanf("%d%lld", &n, &s);
    for (int i = 0; i < n; i++)
        scanf("%lld", &f[i]);
    printf("%lld\n", solve());
    return 0;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116975.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号