Devu和鲜花
作者:互联网
Devu 有 N 个盒子,第 i 个盒子中有 Ai 枝花。
同一个盒子内的花颜色相同,不同盒子内的花颜色不同。
Devu 要从这些盒子中选出 M 枝花组成一束,求共有多少种方案。
若两束花每种颜色的花的数量都相同,则认为这两束花是相同的方案。
隔板法 + 容斥原理
设 \(x_i\) : 第 \(i\) 个盒子拿出的数量. 有 \(x_i \le A_i\), 且 :
\(x_1+x_2+x_3+...+x_n=m\).
令 \(y_i=x_i+1\), 则 \(y_1+y_2+y_3+...+y_n=m-n\).
先不考虑限制, 运用隔板法 : 一共有 \(C_{m+n-1}^{n-1}\) 种可能.
不妨设 \(S_i\) : 第 \(i\) 个盒子超出 \(A_i\) 的集合.
于是答案 : \(ans=C_{m+n-1}^{n-1}-(S_1\cup S_2 \cup S_3 \cup ... \cup S_n)\).
后面那一坨就是容斥原理.
怎么求 \(S_i\) ? \(x_i\ge A_i+1 \Longleftrightarrow y_i\ge A_i +2\), 所以有 :
\(y_1+y_2+y_3+...+y_n=m+n-(A_i+1)\), 继续用隔板法 : \(S_i = C_{m+n-A[i]-1}^{n-1}\)
代码 :
#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define ull unsigned long long
#define pb push_back
#define PII pair<int, int>
#define VIT vector<int>
#define x first
#define y second
#define inf 0x3f3f3f3f
const int N = 20, mod = 1e9 + 7;
ll a[N];
ll down;
ll qmi(ll a, ll k) {
ll res = 1;
while (k) {
if (k & 1) res = res * a % mod;
a = a * a % mod;
k >>= 1;
}
return res;
}
ll C(ll a, ll b) {
if (a < b) return 0;
ll up = 1;
for (ll i = a; i > a - b; --i) up = i % mod * up % mod;
return up * down % mod;
}
int main() {
//freopen("in.txt", "r", stdin);
IO;
down = 1;
ll n, m;
cin >> n >> m;
for (ll i = 1; i <= n - 1; ++i) down = down * i % mod;
down = qmi(down, mod - 2);
for (int i = 0; i < n; ++i) cin >> a[i];
ll ans = C(m + n - 1, n - 1);
for (int i = 1; i < 1 << n; ++i) {
int sign = 1;
ll t = m + n - 1;
for (int j = 0; j < n; ++j)
if (i >> j & 1) {
sign *= -1;
t -= a[j] + 1;
}
ans = (ans + sign * C(t, n - 1)) % mod;
}
ans = (ans + mod) % mod;
cout << ans << '\n';
return 0;
}
标签:盒子,鲜花,int,ll,Devu,ans,mod,define 来源: https://www.cnblogs.com/phr2000/p/15126522.html