首先, 将原问题简化, 假设每种花都有无数多, 从 n 个种类中选出 S 个的方案数
相当于一个长为S的序列, 将其分为n段, 所以答案为
考虑用总的减去不合法的, 因为 n 很小, 所以我们可以枚举不合法的集合
如果 i 不合法, 那么它至少选了 f[i] + 1 个, 剩下的可以随意乱选, 贡献就是
所以对于当前枚举的集合 k , 贡献即为
但是这保证了集合之外的就合法吗? 不
集合之内一定合法, 之外可能合法, 可能不合法, 于是只能容斥原理, 奇加偶减什么的
感性理解一下, 枚举到1不合法, 2也可能不合法, 会把1, 2都算上, 枚举2的时候也会把1算上
于是我们在枚举1, 2的时候减掉
组合数用 Lucas 就可以了, 由于上面的 n-1 很小, 所以直接暴力乘
#include<bits/stdc++.h>
#define N 25
using namespace std;
const int Mod = 1000000007;
typedef long long ll;
int n; ll s, f[N], ans;
ll mul(ll a, ll b){ return (a*b) % Mod;}
ll add(ll a, ll b){ return (a+b) % Mod;}
ll power(ll a, ll b){ ll ans = 1;
for(;b;b>>=1){ if(b&1) ans = mul(ans, a); a = mul(a, a);}
return ans;
}
ll C(int n, int m){
if(n < m) return 0; m = min(m, n - m);
ll up = 1, down = 1;
for(int i=1; i<=m; i++){
up = mul(up, n - i + 1); down = mul(down, i);
} ll ans = mul(up, power(down, Mod-2));
return ans;
}
ll Lucas(ll n, ll m){
if(n < Mod && m < Mod) return C(n, m);
return mul(Lucas(n / Mod, m / Mod), C(n % Mod, m % Mod));
}
int main(){
scanf("%d%lld", &n, &s);
ans = Lucas(n + s - 1, n - 1);
for(int i=1; i<=n; i++) scanf("%lld", &f[i]);
for(int S = 1; S < (1<<n); S++){
ll cnt = 0, res = s;
for(int i=1; i<=n; i++){
if(S & (1<<(i-1))){
cnt++; res -= (f[i] + 1);
}
}
ll tmp = 0;
if(res >= 0) tmp = Lucas(n + res - 1, n - 1);
if(cnt & 1) ans = add(ans, Mod - tmp); else ans = add(ans, tmp);
} printf("%lld", (ans % Mod + Mod) % Mod); return 0;
}