【题解】P5505 [JSOI2011] 分特产
P5505 [JSOI2011] 分特产
题目
给定 \(m\) 个特产,每一个特产都有 \(x_i\) 个,把它分给 \(n\) 个同学。
相同类型的特产是完全一样的,而同学是不一样的。
要求每一个同学至少一个。
思路
很显然发现直接计算是复杂、困难的。
所以我们考虑容斥。
公式如下:
无限制分的情况 - 不合法的情况
Part.A
有限考虑无限制
我们设定:
\(m\) 是盒子数量
\(n\) 是球的数量
我们发现,可以先考虑最少一个的情况。
ULB模型(球相同,盒不同,最少一个)
我们可以列出方程:
\[x_1 + x_2 + \cdots + x_m = n
\]
考虑插板法
其中:\(x_i\) 是不同的板子之间的球个数
即:\(n\) 个球中插入 \(m\) 个板子
正整数解是 \(C[n - 1][m - 1]\)(可以参见OI-wiki)
考虑玩有限制的后,思考无限制的:
ULA模型(球相同,盒不同,无限制)
设 \(y_i\) 为 \(x_i +1\)
那么:
\(y_1 + y_2 ... + y_m = n + m\)
那么解就加上 \(m\),即:
\(C[n + m - 1][m - 1]\)
所以:
原式变为:
\[\sum_{i=1}^{m}{C[x_i + m - 1][m - 1]} - 不合法的情况
\]
Part.B
考虑枚举 \(i\) 使得求和 \(i\) 个盒子为空的情况
对于i个盒子为空的情况:就相当把 \(n\) 个球放进 \(m - i\) 个盒子的情况
根据之前的 ULB 模型:
对于每一个 \(x_i\):
- \(C[x_i + m - i - 1][m - i - 1]\)
所以不合法的情况就是 \(\prod_{i = 1}^{m} C[x_i + m - i - 1][m - i - 1]\)
所以最终的算式就是:
\[\prod_{i=1}^{n} -1 ^{i} \prod_{j = 1}^{m} C[x_j + m - i - 1][m - i - 1]
\]
Part.C
所以,最终算式就是:
\[\sum_{i=1}^{m}{C[x_i + m - 1][m - 1]} - (\prod_{i=1}^{n} -1 ^{i} \prod_{j = 1}^{m} C[x_j + m - i - 1][m - i - 1])
\]
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2010;
const int mod = 1e9 + 7;
int C[N][N]; // ij i qu j
signed main()
{
C[0][0] = 1;
for (int i = 0; i < N; i++)
{
C[i][0] = C[i][i] = 1;
for (int j = 1; j < i; j++)
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
}
int n, m;
cin >> n >> m;
vector <int> a(m + 1);
for (int i = 1; i <= m; i++)
cin >> a[i];
int A = 1, B = 0;
{
for (int i = 1; i <= m; i++)
A *= C[a[i] + n - 1][n - 1], A %= mod;
}
{
for (int i = 1; i < n; i++)
{
int ans = C[n][i];
for (int j = 1; j <= m; j++)
ans = (ans * C[a[j] + n - i - 1][n - i - 1]) % mod;
B += ans * ((i % 2) ? -1 : 1);
B %= mod;
}
}
cout << (A + B + mod) % mod;
return 0;
}

浙公网安备 33010602011771号