zoukankan      html  css  js  c++  java
  • codeforces 451E. Devu and Flowers 容斥原理+lucas

    题目链接

    给n个盒子, 每个盒子里面有f[i]个小球, 然后一共可以取sum个小球。问有多少种取法, 同一个盒子里的小球相同, 不同盒子的不同。

    首先我们知道, n个盒子放sum个小球的方式一共有C(sum+n-1, n-1)种, 但是这个题, 因为每个盒子里的小球有上限, 所有用刚才那种方法不行。

    但是我们可以枚举。 n只有20, 一共(1<<20)-1种状态, 每种状态, 1代表取这个盒子里的小球超过了上限, 0代表没有。

    一共取sum个, 如果一个盒子里面的小球超过了上限, 那么就还剩下sum-f[i]-1个,因为可以为空, 所以要多减一。

    然后就用容斥就可以了。

    lucas定理, C(n, k)%mod p = C(n%p, k%p)*C(n/p, k/p)%mod p, 前面那部分可以直接算, 后面那部分继续lucas递归。

    C(n, k)可以用乘法逆元算。

    #include <iostream>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <set>
    #include <string>
    #include <queue>
    #include <stack>
    #include <bitset>
    using namespace std;
    #define pb(x) push_back(x)
    #define ll long long
    #define mk(x, y) make_pair(x, y)
    #define lson l, m, rt<<1
    #define mem(a) memset(a, 0, sizeof(a))
    #define rson m+1, r, rt<<1|1
    #define mem1(a) memset(a, -1, sizeof(a))
    #define mem2(a) memset(a, 0x3f, sizeof(a))
    #define rep(i, n, a) for(int i = a; i<n; i++)
    #define fi first
    #define se second
    typedef pair<int, int> pll;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const ll mod = 1e9+7;
    const int inf = 1061109567;
    const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
    ll pow(ll a, ll b) {
        ll tmp = 1;
        while(b) {
            if(b&1LL) {
                tmp = tmp*a%mod;
            }
            a = (a*a)%mod;
            b>>=1LL;
        }
        return tmp;
    }
    ll C(ll a, ll b) {
        if(a<b) {
            return 0;
        }
        if(b>a-b) {
            b = a-b;
        }
        ll s1 = 1, s2 = 1;
        for(ll i = 0; i<b; i++) {
            s1 = s1*(a-i)%mod;
            s2 = s2*(i+1)%mod;
        }
        return s1*pow(s2, mod-2)%mod;
    }
    ll lucas(ll a, ll b) {
        if(b == 0)
            return 1;
        return C(a%mod, b%mod)*lucas(a/mod, b/mod)%mod;
    }
    ll a[22];
    int main()
    {
        int n, flag;
        ll s, sum, ans = 0;
        cin>>n>>s;
        for(int i = 0; i<n; i++) {
            scanf("%I64d", &a[i]);
        }
        for(int i = 0; i<(1<<n); i++) {
            sum = s, flag = 1;
            for(int j = 0; j<n; j++) {
                if(i&(1<<j)) {
                    flag *= -1;
                    sum = sum-a[j]-1;
                }
            }
            if(sum<0)
                continue;
            ll tmp = C((sum+n-1)%mod, n-1)%mod;
            ans = (ans+flag*tmp)%mod;
        }
        ans = (ans+mod)%mod;
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    Unity 5.3 Assetbundle热更资源
    自定义协同程序:CustomYieldInstruction
    C# 温故而知新: 线程篇(四)
    C# 温故而知新: 线程篇(三)
    C# 温故而知新: 线程篇(二)
    c# 温故而知新: 线程篇(一)
    C# 温故而知新:Stream篇(六)
    C# 温故而知新:Stream篇(七)
    C# 温故而知新:Stream篇(四)
    Redis高级数据类型
  • 原文地址:https://www.cnblogs.com/yohaha/p/5213269.html
Copyright © 2011-2022 走看看