「HDU 4372」Count the Buildings

Description

Hint

  • \(1\le t\le 10^5\)
  • \(1\le n, f, b\le 2\times 10^3\)

Solution

首先,最高的 \(n\) 一定是两边可以看到的。然后整个状况一定是这样:

YL4kZR.png

我们可以发现,左边的部分可以被分为 \(f - 1\) 组,每一组的开头都为该组一个最高的建筑,其他的由于根本看不见,所以可以随意排列。右边亦是如此。

有一个显而易见的结论: \(n\) 个元素的圆排列种数,与 \(n- 1\) 个元素的排列数相同。

于是可以这样理解: 将最高楼左右分别分为 \(f - 1, b - 1\) 组,每一组内部任意做圆排列

这就是 第一类斯特林数

第一类斯特林数 \(\begin{bmatrix}n\\ k\end{bmatrix}\) 表示 \(n\) 个不同元素分为 \(k\) 个非空圆排列的方案数。

递推式: \(\begin{bmatrix}n\\ k\end{bmatrix} = \begin{bmatrix}n - 1\\ k-1\end{bmatrix} + (n-1)\begin{bmatrix}n-1\\ k\end{bmatrix}\)

然后在所有 \(f + b - 2\) 组中,选取 \(f - 1\) 个置于左侧,其余的组置于右侧,那么这就相当于 \(\large{{f + b - 2}\choose {f - 1}}\)

答案:\(\begin{bmatrix}n - 1\\ f + b - 2\end{bmatrix} \times \large{{f + b - 2}\choose {f - 1}}\)

复杂度:\(O(n^2 + t)\)

Code

#include <iostream>

using namespace std;
const int N = 2e3 + 5;
const int mod = 1e9 + 7;

long long s[N][N];
long long c[N][N];

void init(int n = 2e3) {
	s[0][0] = s[1][1] = 1ll;
	for (register int i = 2; i <= n; i++)
		for (register int j = 1; j <= i; j++)
			s[i][j] = (s[i - 1][j - 1] + (i - 1) * s[i - 1][j]) % mod;
	
	for (register int i = 0; i <= n; i++) {
		c[i][0] = c[i][i] = 1ll;
		for (register int j = 1; j < i; j++)
			c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
	}
}

signed main() {
	init();
	int t; cin >> t;
	
	while (t--) {
		int n, f, b;
		cin >> n >> f >> b;
		if (f + b - 2 > n - 1) cout << 0 << endl;
		else cout << s[n - 1][f + b - 2] * c[f + b - 2][f - 1] % mod << endl;
	}
}

猜你喜欢

转载自www.cnblogs.com/-Wallace-/p/12935802.html