【题解】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;
}
posted @ 2026-09-18 16:49  Axor  阅读(9)  评论(1)    收藏  举报