学习笔记之组合排列(学习中)

一:基础工具与方法
加法原理:完成一件事情若有 a 种方法与 b 种方法,则总方法数为 a + b 种。
乘法原理:完成一件事情若需前后两步,第一步有 a 种方法,第二步有 b 种方法,则完成这件事有 a * b 种方法。
容斥原理:设 n 个集合 S 为有限集合, |S| 表示集合大小,则:

\[\mid \bigcup_{i = 1}^{n} S_i \mid = \sum_{i = 1}^{n}\mid S_i \mid - \sum_{1 \le i < j \le n} \mid S_i \cap S_j\mid + \sum_{1 \le i < j < k \le n} \mid S_i \cap S_j \cap S_k \mid + \]

\[... + (-1)^{n + 1} \mid S_1 \cap ... \cap S_n \mid \]

排列数(符号:A):从 n 个不同元素中取 m 排成一列,可产生排列数量为:

\[A_n^m = \frac{n!}{(n - m)!} = n \times (n - 1) \times ... \times (n - m + 1) \]

组合数(符号:C):从 n 个元素中取 m 个组成一个集合(无关顺序),可产生集合数量为:

\[C_n^m = (_m^n) = \frac{A_n^m}{A_m^m} = \frac{n!}{m!(n - m)!} = \frac{n \times (n - 1) \times ... \times (n - m + 1)}{m \times (m - 1) \times ... \times 2 \times 1} \]

——有关组合数相关性质:
\(C_n^m = C_n^{n - m}\)
\(C_n^m = C_{n - 1}^{m} + C_{n - 1}^{m - 1}\)
\(C_n^0 + C_n^1 + C_n^2 + ... + C_n^n = 2^n\)
——证明如下:
一:对于每个 n 个数中取出 m 个数的集合,剩下 m - n 个数同样构成一个集合,两个集合一一对应,所以性质一成立。
二:从 n 个元素中取 m 个元素构成集合有两类方法:若取第 n 号元素,则再从剩下 n - 1 个元素选 m - 1 个,有 \(C_{n - 1}^{m - 1}\) 种方法。若不取,则从剩下 n - 1 个元素中选 m 个,有 \(C_{n - 1}^{m}\) 种方法。根据加法原理,得 \(C_n^m = C_{n - 1}^{m} + C_{n - 1}^{m - 1}\) ,所以性质二成立。
三:假设从 n 个元素中选出若干个元素构成一个集合,根据加法原理,共有 \(C_n^0 + C_n^1 + C_n^2 + ... + C_n^n = 2^n\) 种方法;又想到每个元素有取与不取两种状态,根据乘法原理可知,共有 \(2^n\) 种方法。即得 \(C_n^0 + C_n^1 + C_n^2 + ... + C_n^n = 2^n\) ,所以性质三成立。
——证毕。
卡特兰数:给定 n 个 -1 与 n 个 -1 ,以某种顺序构成长度为 2n 的序列,满足任意一段前缀和都大于等于 0 的序列个数为:

\[Cat_n = \frac{C_{2n}^{n}}{n + 1} \]

——证明如下:
易求所有长度为 2n 的序列数为 \(C_{2n}^{n}\) 个。
那么不妨假设满足要求的序列有 A 个,不满足的有 B 组,得 \(A + B = C_{2n}^{n}\) ,那么目标变成了求出 B 是多少。
注意到对于每一个 B 类序列,都存在一个最小位置 2p + 1 , 其中 -1 有 p + 1 个,1 有 p 个。再将区间 [2p + 2 ~ n] 中的数全部取反,得到 -1 有 n - p - 1 个,得到 1 有 n - p 个,此时这个序列有了 n + 1 个 1 与 n - 1 个 -1的序列。于是,我们只要求出这样的序列有几个就可以了,显然有 \(C_{2n}^{n - 1}\) 个。那么便推出式子:

\[C_{2n}^{n} - C_{2n}^{n - 1} = \frac{(2n)!}{n!n!} - \frac{(2n)!}{(n-1)!(n+1)!} = \frac{(2n)!}{n!n!} - \frac{(2n)!}{n!n!(n+1)} \]

\[= \frac{(2n)!}{n!n!} \times \frac{1}{n + 1} = Cat_n \]

——证毕。
第一类斯特林数:给定 p 个不同对象,将其排成 k 个非空循环排列的方法数为第一类斯特林数:

\[s(p, k) = s(p - 1, k - 1) + s(p - 1, k)(p - 1), \]

\[s(p, p) = 1, s(p, 0) = 0 \]

——证明如下:
给定 p 个对象,将其排成 k 个非空循环排列有两类方法:若将第 p 号元素单独放一个排列,则有 \(s(p - 1, k - 1)\) 种方法;若放入已有排列中,那么它可以在 1 ~ (p - 1) 号元素的左侧,有 \(s(p - 1, k)(p - 1)\) 种方法。则

\[s(p, k) = s(p - 1, k - 1) + s(p - 1, k)(p - 1) \]

——证毕。
第二类斯特林数:给定 p 个不同对象,将其组合成 k 个非空集合的方法数为第二类斯特林数:

\[s(p, k) = s(p - 1, k - 1) + s(p - 1, k)k, \]

\[s(p, p) = 1, s(p, 0) = 0 \]

——证明如下:
给定 p 个对象,将其组合成 k 个非空集合有两类方法:若将第 p 号元素单独放一个集合,则有 \(s(p - 1, k - 1)\) 种方法;若放入已有集合中,那么它可以在 1 ~ k 号集合中,有 $s(p - 1, k)k $ 种方法。则

\[s(p, k) = s(p - 1, k - 1) + s(p - 1, k)k \]

——证毕。
挡板法:将 n 个相同元素组成 m 个不同非空集合的方法数为:

\[C_{n - 1}^{m - 1} \]

思想:由于元素相同,排成一排后构成了 n - 1 个空隙,问题便转化成了往 n - 1 个空隙中放置 m - 1 个挡板,得出式子。
挡板法其二:将 n 个相同元素组成 m 个不同集合(集合允许为空)的方法数为:

\[C_{n + m - 1}^{m - 1} \]

思想:n - 1 个空隙再加上 m 个可能的空集即可。
DP法:视题目而论,这里不做过多介绍。
关于排列数,组合数,第一第二类斯特林数代码如下

点击查看代码
int C(int x, int y) {
	if (x < y) return 0;
	int a = 1;
	for (int i = 1; i <= y; i++)
		a = a * (x - y + i) / i;
	return a;
}

int A(int x, int y) {
	if (x < y) return 0;
	int a = 1;
	for (int i = x - y + 1; i <= x; i++)
		a *= i;
	return a;
}

int stirling_1(int p, int k) {
	if (p == k) return 1;
	if (k == 0 || p < k) return 0;
	return stirling_1(p - 1, k - 1) + (p - 1) * stirling_1(p - 1, k);
}

int stirling_2(int p, int k) {
	if (p == k) return 1;
	if (k == 0 || p < k) return 0;
	return stirling_2(p - 1, k - 1) + k * stirling_2(p - 1, k);
}

二:经典例题分析
一:1, 2, 3,..., n 经过一个栈,有多少种合法的出栈顺序。
方法:将入栈操作看作 1 ,出栈操作看作 -1 。问题变成了给定 n 个 -1 与 n 个 -1 ,以某种顺序构成长度为 2n 的序列,求满足任意一段前缀和都大于等于 0 的序列个数,用卡特兰数即可。
二:题目:https://www.luogu.com.cn/problem/P10937
方法:将 L 形分成两部分,枚举其中一块里车的数量,易得公式:

\[\sum_{i = 0}^{k}C_a^iC_{b + d - i + k}^ii!C_c^{k - i}C_d^{k - i}(k - i)! \]

易错点:考虑到第一部分要预留 k - i 行给第二部分放,便有了 b + d - i + k 这一式子。

posted @ 2024-12-22 14:32  Jiaminyo  阅读(101)  评论(0)    收藏  举报