【多重集组合数】 Devu and Flowers
传送门
题意
给定\(n\)和\(s\),表示有\(n\)个箱子要取\(s\)朵花,每个箱子表示一个种类的花,每个箱子中花的数量分别是
\[f_{1} , f_{2} , \dots , f_{n}
\]
求出不同的选取方案
数据范围
\(1 \leq n \leq 20\)
\(0 \leq s \leq 10^{14}\)
\(0 \leq f_{i} \leq 10^{12}\)
题解
多重集合的组合数模板,容斥原理通过二进制数表示选择的个数
Code
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=30,mod=1e9+7;
ll f[N];
ll down;
ll quick_pow(ll a, ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
ll C(ll a,ll b){
if(a<b) return 0;
ll res=1;
for(ll i=a;i>a-b;i--) res=i%mod*res%mod;
return res*down%mod;
}
int main(){
ll n, s;
cin >> n >> s;
for (int i = 0; i < n; i ++ ) cin >> f[i];
down=1;
for (ll j = 1; j <= n - 1; j ++ ) down = j * down % mod;
down = quick_pow(down, mod - 2);
int res = 0;
for(int i=0;i<1<<n;i++){
ll sign=1;
ll a=n+s-1;
for(int k=0;k<n;k++){
if(i>>k&1){
sign*=(-1);
a-=f[k]+1;
}
}
res = (res + C(a, n-1) * sign) % mod;
}
cout<<(res+mod)%mod<<endl;
}