18 ,组合数学,容斥,Lucas

CodeForces - 451E 

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).

Examples

Input

2 3
1 3

Output

2

Input

2 4
2 2

Output

1

Input

3 5
1 3 2

Output

3

题目的大意就是给你s朵小花,然后让你放到n个花瓶里面,每一个花瓶有一个放花的上限,让我们求算一下所有的方案数,

假设我们现在有6朵花放到5个瓶子里面先不考虑不合适的情况会有c(5-1,5+6-1)种情况,就是C(n-1,s+n-1)证明如下

我们可以采用隔办法来实现 假设我们有6朵花如下,显然如果将其放到两个瓶子中时有

  *   *   *   *   *   *   |

放到2个瓶子可以有7种选择

放到3个瓶子可以有7*8种选择

放到4个瓶子可以有7*8*9种选择

放到5个瓶子可以有7*8*9*10种选择

但是因为瓶子是相同的所以我们要的不是排列而是一个组合,所有还有除以4的阶乘就可以得到了

就是从s+1向上乘以n-1个数字,在除以n-1的阶乘就是C(n-1, s+n-1),这就是所有的方案数,但是会有不合法的

下一步就是要减去不合法的我们来考虑一下就是对于第i个瓶子如果是不合法的话那么这瓶子里面至少有f[i]+1 朵花

对于剩下的话我们的排放方案有入下我们会有C(n-1   ,  s - f[i] -1 + n-1 )种方案,这个就第i个瓶子装的不合法,其他

的瓶子随便放的方案数,一个瓶子的情况有两种就是随便放跟不合法,如果我们用0表示随便放,1表示不合法的话

那么所有的瓶子随便放不合法情况会有2的n次方种方案

瓶子号     :  5   4    3    2     1 

情况  0     :  0   0    0     0     0   那么我么就要留下这时候是C( n-1,s+n-1);

         1       :   0   0    0     0      1  只有1是不合法的其他的都是随便放;有C( n-1, s - f[1] -1 +  n -1 ) ( 减 掉);

         2       :   0    0   0     1      0  只有1是不合法的其他的都是随便放;有C(n-1, s-f[2] - 1 +  n -1)(减掉);

         3       :   0    0    0     1      1 只有1和3是不合的其他的都是随便放;有C(n-1 ,s - f[2] - 1 -f[3] - 1 + n -1 )(?);

                    ...............................

         31     :   1    1    1    1       1

        对于情况3我们是减掉呢还是加上呢,显然是加上,因为1不合法的时候我们会减掉2不合法并且其他随便的情况,

        2不合法的时候我们会减掉1不合法其他都是随便的情况,这个样子我们会把1和2都不合法其他的都随便的情况给

       减了两次也就是情况3,这个时候我们要把情况3给加上就那么我们就可以对于瓶子1不合法,瓶子2不合法的方案就

       给减掉了,之后我们要用到一下Lucas来求一下组合数就是在s减掉相应的f[i]的时候我们要判断一下最后的s是否是为

      零如果是为零的话我们,那么就不能再分了

     #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,s,n) for(ll i=s;i<=n;i++)
#define per(i,n,s) for(ll i=n;i>=s;i--)
const int Max = 2e5+10;
const int maxn = 2e5+10;
const ll mod  = 1e9+7;
ll mod_pow(ll x, ll n, ll mod){
    ll ret = 1ll;
    while(n > 0){
        if(n & 1) ret = ret * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return ret;
}
ll C(ll m, ll n, ll p){
    if(n < m) return 0;
    if(m > n - m){
        m = n - m;
    }
    ll up = 1, down = 1;
    for(ll i = 0;i < m;i ++){
        up = up * (n - i) % p;
        down = down * (i + 1) % p;
    }
    return up * mod_pow(down, p - 2, p) % p;
}
ll Lucas(ll m, ll n, ll p){
    if(m == 0) return 1;
    return C(m % p, n % p, p) * Lucas(m / p, n / p, p) % p;
}
ll ff[Max];
ll a[Max];
int sa[50];
int main(){
    ll s,n;
    scanf("%lld %lld",&n,&s);
    rep(i,0,n-1)  scanf("%lld",&a[i]);
    ll son=n-1;
    ll sum=0;
    ll base;
    rep(i,0,(1<<n)-1){
        base=s;
        int f=1;
        ll j=i;
        int len=0;
        while(j){
            sa[len++]=j%2;
            j/=2;
            if(sa[len-1]==1){
                base=base-a[len-1]-1;
                f*=-1;
            }
        }
        base=base+n-1;
        if(base<0) continue;
        if(f==1){
            sum=(sum + Lucas (son,base,mod) ) % mod ;
            sum=(sum % mod + mod ) % mod ;
        }
        else {
            sum=(sum- Lucas (son,base,mod))%mod;
            sum=(sum%mod+mod)%mod;
        }
    }
    printf("%lld\n",(sum%mod+mod)%mod);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39792342/article/details/81937446