首页 > 代码库 > Codeforces Round #258 E Devu and Flowers --容斥原理

Codeforces Round #258 E Devu and Flowers --容斥原理

这题又是容斥原理,最近各种做容斥原理啊。当然,好像题解给的不是容斥原理的方法,而是用到Lucas定理好像。这里只讲容斥的做法。

题意:从n个容器中总共取s朵花出来,问有多少种情况。其中告诉你每个盒子中有多少朵花。

分析:其实就是求方程: x1+x2+...+xn = s 的整数解的个数,方程满足: 0<=x1<=a[1], 0<=x2<=a[2]...

设:A1 = {x1 >= a[1]+1} , A2 = {x2 >= a[2]+1} , .... , An = {xn >= a[n]+1}. 全集S = (n+s-1,s)

所以容斥原理可求得答案。

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define Mod 1000000007#define lll __int64#define ll long longusing namespace std;#define N 100007ll a[22];ll inv[30];ll fastm(ll a,ll b){    ll res = 1LL;    while(b)    {        if(b&1LL)            res = (res*a)%Mod;        b >>= 1;        a = (a*a)%Mod;    }    return res;}ll comb(ll n,ll r){    if(r > n)        return 0;    r = min(r,n-r);    n%=Mod;    ll ans = 1LL;    for(int i=0;i<=r-1;i++)    {        ans = ans*(n-i)%Mod;        ans = ans*inv[i+1]%Mod;    }    return ans;}int calc(int s){    int cnt = 0;    while(s)    {        if(s&1)            cnt++;        s >>= 1;    }    return cnt;}int main(){    int n,i;    ll s;    for(i=1;i<=30;i++)        inv[i] = fastm(i,Mod-2);    while(cin>>n>>s)    {        for(i=0;i<n;i++)            cin>>a[i];        ll ans = 0;        int S = (1<<n)-1;        for(int state=0;state<=S;state++)        {            ll r = s;            int tmp = state;            int cnt = calc(state);            i=0;            while(i<n)            {                if(tmp&1)                    r -= (a[i]+1);                tmp >>= 1;                i++;            }            if(r < 0)                continue;            ll cb = comb(n+r-1,r);            if(cnt%2)                cb = -cb;            ans = (ans+cb+Mod)%Mod;        }        printf("%I64d\n",ans);    }    return 0;}
View Code

 

Codeforces Round #258 E Devu and Flowers --容斥原理