一些组合数学

  • 错排

\[f(x) = (x-1)(f(x-1)+f(x-2)) \]

\(f(x)\) 含义为放置的所有数中有 \(x\) 个数错位排列的情况数。

假定当前准备放置第 \(x\) 个数。初始时将第 \(x\) 个数放在标号为 \(x\) 的位置。此时需要将 \(x\) 与前 \(x-1\) 个数中的某一个交换

若前 \(x-1\) 个数均错位排列,那么目前有 \(x-1\) 种交换方案,即 \(f(x) \leftarrow (x-1)*f(x-1)\)

若前 \(x-1\) 个数中仅有一个没有错位排列,那么必须将第 \(x\) 个数与那个没有错排的数交换。共有 \(n-1\) 种一个数没有错排的情况。那么, \(f(x) \leftarrow (x-1)*f(x-2)*1\)

若前 \(x-1\) 个数中存在多于一个数没有错位排列,此时无法通过一次交换使得所有数均错位排列。

综上,\(f(x) = (x-1)(f(x-1)+f(x-2))\)

  • 一些二项式定理的推论

\(\sum\limits_{i=0}^n {\dbinom{n}{i}} = 2^n \ \ \ \ \ \ \ \ \sum\limits_{i=0}^n (-1)^i {\dbinom{n}{i}} = 0\)

  • \(\text{Catalan Number}\) 式子

\(H(x) = \begin{cases} 1 & x \leq 2 \\ \frac{\binom{2n}{n}}{n+1} & x>2 \\ \sum\limits_{i=1}^{n}{H(i-1)*H(x-i)} & x>2 \end{cases}\)

  • \(\text{Stirling Number}\) 式子

第一类(stirling轮换数)

\(\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} \]

将第 \(n\) 个数划分为一个新的排列,即 \(\begin{bmatrix} n \\ k \end{bmatrix} \leftarrow \begin{bmatrix} n-1 \\ k-1 \end{bmatrix}\)

将第 \(n\) 个数插入到一个已有的排列中。因为是圆排列,所以插入到 \(n-1\) 个已有元素中的任意一个的后面都可以计入答案。 \(\begin{bmatrix} n \\ k \end{bmatrix} \leftarrow (n-1) \begin{bmatrix} n-1 \\ k \end{bmatrix}\)

性质: \(n! = \sum\limits_{i=0}^{n} {\begin{bmatrix} n \\ i \end{bmatrix}}\)

第二类(stirling子集数)

\(\begin{Bmatrix} n \\ k \end{Bmatrix}\) 表示将 \(n\) 个数划分成 \(k\) 个集合的方案数

\[\begin{Bmatrix} n \\ k \end{Bmatrix} = \begin{Bmatrix} n-1 \\ k-1 \end{Bmatrix} + (k-1) \begin{Bmatrix} n-1 \\ k \end{Bmatrix} \]

将第 \(n\) 个数划分为一个新的集合,即 \(\begin{Bmatrix} n \\ k \end{Bmatrix} \leftarrow \begin{Bmatrix} n-1 \\ k-1 \end{Bmatrix}\)

将第 \(n\) 个数插入到一个已有的集合中,即 \(\begin{Bmatrix} n \\ k \end{Bmatrix} \leftarrow (k-1) \begin{Bmatrix} n-1 \\ k \end{Bmatrix}\)

性质: $x^n = \sum\limits_{i=0}^{x} { {\begin{Bmatrix} n \ i \end{Bmatrix}} * i! * \dbinom{x}{i} } $

  • \(\text{Min-Max}\) 容斥

\[max(S) = \sum\limits_{T \subseteq S} {(-1)^{|T|+1}min(T)} \]

证明:

\(A_i\) 表示对 \(S\) 集合排序后第 \(i\) 大的数。

\(min(S)=A_1\) ,则 \(S = \{A_1\}\)

对于这种情况,对答案的贡献为 \((-1)^{1+1}A_1 = A_1\)

\(min(S) = A_k \ (k > 1)\) ,则 \(S = \{\dots A_a \dots A_b \dots A_c \dots A_k\}\) 。即, \(A_1\)\(A_{k-1}\) 所有元素的某个子集再加上 \(A_k\) 本身。

对于这种情况,观察可知 \(A_1\)\(A_k\) 所有元素的子集中,大小为奇数的集合与大小为偶数的集合数量相等。因此,对答案的贡献为 \(0\)

综上,答案恰为 \(A_1\) ,即 \(max(S)\)

例题:[HAOI2015] 按位或

拆位考虑,答案即为 \(E(max\{T\})\) ,其中 \(E(x)\) 表示 \(x\) 中元素的最晚出现时间的期望。注意, \(x\) 是一个二进制数,代表一个集合。若其中第 \(i\) 位为 \(1\) 则表示集合中存在 \(i\)

直接求解较为困难,故可以转为求解 \(E(min\{T\})\) ,再容斥得出答案。

$E(max{T}) = \sum\limits_{T \subseteq x} {(-1)^{|T|+1}E(min{T})} \ \ $ 那么,如果对于任意集合 \(T\) ,可以迅速求出 \(E(min\{T\})\) ,本题就得到解决。

\(E(min\{T\}) = \dfrac{1}{\sum\limits_{G \cap T \ne \empty} {P_G}}\) 。分母的那个sum求解较为困难,但发现分母可以当成 \(G\) 的补集的子集和;而子集和可以预处理的出。于是本题得解。

#include <bits/stdc++.h>

using namespace std;

#define M 1100005

int n, popcnt[M], flag[M];
double ans, p[M], sum[M];

int main()
{
	scanf("%d", &n);
	for (int i = 0; i < (1<<n); i++)
		scanf("%lf", &p[i]);

	for (int i = 0; i < (1<<n); i++)
	{
		popcnt[i] = popcnt[i>>1] + (i&1);
		flag[i] = (((popcnt[i]+1)&1) ? -1 : 1);
	}

	for (int len = 2; len <= (1<<n); len <<= 1)
		for (int i = 0; i < (1<<n); i += len)
			for (int j = 0; j < (len>>1); j++)
				p[i+j+(len>>1)] += p[i+j]; // 预处理子集和

	double ans = 0;
	for (int sta = 1; sta < (1<<n); sta++)
		if (1-p[((1<<n)-1) ^ sta] > 1e-10)
			ans += 1.0 * flag[sta] / (1-p[((1<<n)-1) ^ sta]); // min-max容斥

	if (ans < 1e-10) puts("INF");
	else printf("%.11lf\n", ans);

	return 0;
}

\(\text{Kth-Min-Max}\) 容斥

\[kth\ max(S) = \sum\limits_{T \subseteq S} {(-1)^{|T|-k} \binom{|T|-1}{k-1} min(T)} \]

证明略。

例:重返现世

\(\text{Kth-Min-Max}\) 板子。

对所有原料的期望出现时间排序,那么答案为出现时间第 \(k\) 小的元素的出现时间。(即,第 \(n-k+1\) 大)

本题的难点在于加速运算。发现 \(n \le 1000\) ,故直接枚举子集不可取。

posted @ 2020-12-10 17:45  MikeDuke  阅读(156)  评论(0)    收藏  举报