一、多重集的组合数:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<string>
#define ll long long
using namespace std;
const int p=1000000007;
const int maxn=25;
ll a[maxn],inv[maxn];
ll n,m,ans=0;
ll mypow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=(ans*a)%p;
a=(a*a)%p;
b>>=1;
}
return ans%p;
}
ll C(ll n,ll m)
{
if(n<0||m<0||n<m) return 0;
n%=p;
if(n==0||m==0) return 1;
ll ans=1;
for(int i=1;i<=m;i++)
{
ans=(ans*(n-m+i))%p;
ans=(ans*inv[i])%p;
}
return ans;
}
int main(void)
{
for(int i=1;i<=20;i++)
{
inv[i]=mypow(i,p-2);
}
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int x=0;x<(1<<n);x++)
{
if(x==0)
ans=(ans+C(n+m-1,n-1))%p;
else
{
ll t=n+m;
ll cnt=0;
for(int i=0;i<n;i++)
{
if((x>>i)&1) cnt++,t-=a[i+1];
}
t-=cnt+1;
if(cnt&1)
ans=(ans-C(t,n-1))%p;
else ans=(ans+C(t,n-1))%p;
}
}
printf("%lld\n",(ans+p)%p);
return 0;
}