组合数学

你睁开眼睛,周身一片死寂,黑暗包裹着你;随后一片金色和蓝色缓慢升起,丝线缠绕,白色的裙袂在眼前飞舞。

你睁开眼睛,你看见了她,曾在去年的深秋与你立下约定。

她在叹息的盛夏向你发出邀请,在热烈的深秋与你相知相依。你记得的,她那时候说了什么?站在舞台之上,露出那种温柔的笑意,你很熟悉。她说:我们还会再见面,我还会站在你面前。

是啊,她答应你了,她说过还想见你。 你坐起身,去触碰她,但她笑着收回手。她看着你,眼睛一如既往美丽,闪烁绿色的荧光。她轻声说:再等等,与我相爱的人啊,再等候我吧。

我们一定会再见面的,在流光之奏中,在共鸣之音下。

然后她退后,星光缠绕着她,也缠绕着你。梦境将醒,但你并不惆怅——啊,你知晓的:你们马上要相见了。

——


组合计数

不会数数。

天依宝宝可爱!


常用恒等式

二项式定理:

\[(a+b)^n = \sum _{i=0} ^n \binom n i a^i b^{n-i} \]

杨辉三角(容易忘记用):

\[\binom n m = \binom n {m-1} + \binom {n-1} {m-1} \]

范德蒙德卷积(重要的):

\[\sum _{i=0} ^k \binom n i \binom m {k-i} = \binom {n+m} k \]

证明考虑把 \(n+m\) 个元素分成两份,一份有 \(n\) 个,另一份有 \(m\) 个,然后等号右边就是直接组合数,等号左边是先考虑两份分别选几个在加法原理。显然两者是等价的。

范德蒙德卷积的形式就是上标固定,下标和固定,且 \(\sum\) 能从 \(0\) 取到满。

变式 #1:

\[\sum _{i=-r} ^s \binom n {r+i} \binom m {s-i} = \binom {n+m} {r+s} \]

变式 #2:

\[\sum _{i=0} ^n \binom n i ^2 = \binom {2n} n \]

变式 #3:

\[\sum _{i=0} ^m \binom n i \binom m i = \binom {n+m} m \]

证明:因为 \(\binom m i = \binom m {m-i}\),所以……就证出来了。

二项式反演

\(f_i\)钦定\(i\) 个什么东西(\(\ge i\))的方案数,\(g_i\)恰好 \(i\) 个的方案数,则有:

\[\begin{aligned} f_n & = \sum _{i=n} ^{\infin} \binom i n g_i \\ g_n & = \sum _{i=n} ^{\infin} (-1)^{i-n} \binom i n f_i \end{aligned} \]

其中 \(\infin\) 为题意中指定的上限。

\(f_i\)钦定最多 \(i\) 个(\(\le i\))的方案数,\(g_i\)恰好 \(i\) 个的方案数,则有:

\[\begin{aligned} f_n & = \sum _{i=0} ^n \binom n i g_i \\ g_n & = \sum _{i=0} ^n (-1)^{n-i} \binom n i f_i \end{aligned} \]

严格证明见这里,但是因为这里是 OI 而不是 MO,所以只背过结论就可以了,并不需要证明。

记忆技巧:\(f\)\(g\) 交换位置,\(\sum\) 不变,组合数不变,乘上一个 \(-1\) 的「\(n,i\) 中大的减小的」次方。


洛谷 P5505 | 二项式反演

思维难度:\(\color{#F39C11} 橙\) *900

以前拿容斥做过,但是,

组合意义天地灭,代数推导保平安。

\(f_i\) 为钦定 \(i\) 个人不选所得到的方案数,枚举钦定的是哪些人,考虑隔板法,有:

\[f_i = \binom n i \prod _{j=1} ^m \binom {a_j + n - i - 1} {a_j} \]

然后反演得到 \(g_i\) 为恰好 \(i\) 个人不选的方案数,于是 \(g_0\) 即为所求。

\(f_i\) 的复杂度为 \(O(m)\),求 \(g_0\) 需要 \(n\)\(f_i\),所以总复杂度 \(O(nm)\)

submission

天依宝宝可爱!


洛谷 P4859

思维难度:\(\color{#52C41A} 绿\) *1600

怎么又是 dp,怎么 dp 总是在想不到的地方出现。

显然可以二项式反演,于是只需要求 \(f_i\) 表示钦定 \(i\)\(a_x > b_y\) 的方案数。

但是发现这个东西好像不好直接组合数,所以考虑 dp。不过 dp 好像是三维的,不仅需要记录在两个序列分别遍历到了哪里,还要记录当前选了几对。

有一个很神奇的转化,注意到我们并不怎么关心两个序列分别遍历到了哪,只关心元素的相对大小,所以考虑把两个序列合并起来排序并标记每个元素来自哪个序列,这样就会惊奇地发现 dp 状态减少了一维,还更好转移。

\(g_{i,j}\) 为前 \(i\) 个元素,选了 \(j\)\(a_x > b_y\) 的方案数,于是考虑当前元素属于 \(a\) 还是属于 \(b\),若属于 \(a\) 再考虑是否与之前未选择的 \(b\) 中元素构成 \(a_x > b_y\) 的关系即可。

submission

天依宝宝可爱!


洛谷 P3214

思维难度:\(\color{#3498DB} 蓝\) *2000

神仙题。标「†」是神仙的地方。

那么就是要求 \(\{ 1,2,3\ldots,n \}\) 这个集合的若干个子集,†考虑转化为二进制表示 \(i\) 是否在所选子集内,那么就得到了 \(2^n\) 个集合,题意就转化成了在 \(2^n\) 个数中选 \(m\) 个满足以下条件:

  1. 选择的数两两不同。
  2. †所有数的异或和 \(=0\)。这是为了满足偶数的限制。
  3. 不能选 \(0\)

\(f_i\) 为满足上面条件的选 \(i\) 个数的方案。

为了满足异或和为 \(0\),†可以这么想,考虑先随便选 \(i-1\) 个两两不同的元素,然后再选与这些元素的异或和相等的元素 \(x\),于是总方案数就是 \(\binom {2^n - 1} {i - 1}\)。这里先不考虑算重,因为显然每个方案被算了 \(i\) 次,最后除以 \(i\) 即可。

但是这样就无法保证满足条件 #1 #3 了,因为随便选的元素的异或和是什么我们不知道,于是考虑单步容斥把这两部分砍掉。

先看 #3,可以发现当且仅当随便选的元素异或和为 \(0\) 时,才会出现 \(x\)\(0\) 的情况,而这正好对应了 \(f_{i-1}\) 的定义,于是需要减掉 \(f_{i-1}\)

再看 #1,我们需要在减去不满足 #1 的方案的情况下,不能多减不满足 #3 的方案。考虑当且仅当随便选的元素中出现 \(x\) 时会出现这种情况,于是枚举每个 \(x\),那么剩下的 \(i-2\) 就需要满足异或和为 \(0\) 了,我们惊奇地发现正好对应的是 \(f_{i-2}\)。然后考虑对于一个 \(f_{i-2}\) 的方案,在 \(2^n - 1\) 个位置中已经确定了 \(i-2\) 个位置,于是还剩下 \(2^n - 1 - (i-2)\) 个位置可以放 \(x\)。所以要减去 \(f_{i-2} \times (2^n - 1 - (i-2))\)

当然最后需要除以 \(i\)

于是就得到了递推式:

\[f_i = \frac 1 i \left( \binom {2^n - 1} {i-1} - f_{i-1} - f_{i-2} \times (2^n - 1 - (i-2)) \right) \]

submission

天依宝宝可爱!


洛谷 P7322

思维难度:\(\color{#52C41A} 绿\) *1700

怎么想到的啊啊啊……

直接针对每个数统计出现次数,好像是可以做的,但是好像要容斥,好像复杂度还很不好保证。

考虑一个序列的滑动窗口 max,一定是分为若干段的,而且因为是排列所以每段都不同。所以只需要求 max 变化的次数就可以了。可以发现从 \([l,r]\)\([l+1,r+1]\) 时 max 发生变化有这两种情况:

  • \(\displaystyle \max _{i=l} ^{r+1} \{ a_i \} = a_{r+1}\)
  • \(\displaystyle \max _{i=l} ^{r+1} \{ a_i \} = a_l\)

注意到两者其实是对称的,所以只需要求出第一个的答案然后乘 \(2\) 即可。

这部分数数是容易的。先枚举一个 \(a_{r+1}\)(令为 \(a_i\)),考虑这个窗口在什么位置,\(a_i\) 左边选 \(k\)\(< a_i\) 的数是什么,以及窗口内和窗口外分别随便排列,则答案为:

\[\sum _{i=k+1} ^n (n-k) \binom {i-1} k k! (n-1-k)! \]

于是这个乘 \(2\) 即可。

注意到我们只统计了变化量但没有统计初始量,所以还要加上一个 \(n!\)

submission

天依宝宝可爱!


洛谷 P2290

思维难度:\(\color{#F39C11} 橙\) *1100

Prüfer 序列,可以把一棵树转化成一个序列,且树和序列之间构成双射。构造方式是每次选当前剩余的所有点中,编号最小的度数为 \(1\) 的点,将它连向的父节点编号插入序列末尾,并将这个点以及这条边删除。最后整棵树只剩 \(2\) 个点的时候结束。

那么就得到了一个长度为 \(n-2\) 的序列。可以发现这个序列可以随便排,总能找到唯一对应的一棵树。

Prüfer 序列的一些性质:

  1. Prüfer 序列与无根树构成双射。
  2. \(n\) 个有编号节点任意连边能构成不同(不是本质不同)的树的个数为 \(n^{n-2}\);一个有 \(n\) 个节点的完全无向图的生成树个数为 \(n^{n-2}\)
  3. 度数为 \(d\) 的点在 Prüfer 序列中恰好出现 \(d-1\) 次。

于是这个题就转化成了让 \(i\) 在长度为 \(n-2\) 的序列中出现 \(d_i - 1\) 的方案数,显然就是可重集上的全排列了。

但是不取模,所以要预处理分解质因数。

submission

天依宝宝可爱!


CF559C

思维难度:\(\color{#FFC116} 黄\) *1400

做过,原题是 AT_dp_y。

啊…?原来这个题我也做过。细思极恐。

submission

天依宝宝可爱!


洛谷 P3266

思维难度:\(\color{#3498DB} 蓝\) *2300

又是神仙题。

不过先不看这个题,而是考虑这样一个问题:

在一个平面坐标系上,给定起点 \((0,0)\) 和终点 \((n,m)\),以及两条直线 \(y=x+a\)\(y=x-b\),求从起点走到终点且不经过两条直线的方案数。保证起点和终点都在两条直线之间。

如果没有限制,方案显然为 \(\binom {n+m} n\)

如果只有一条直线的限制,考虑单步容斥。将不合法的路径翻折(仅翻折最后一次碰线之前的部分)后,可以发现这些路径都是从 \((0,0)\) 关于直线的对称点出发走到 \((n,m)\) 的,而且两者构成双射,所以直接减去这些路径就可以了。

那么考虑两条直线的情况。

懒得画图了,搬 题解 里的图吧。

如上图,可以发现这时候直接容斥是不好做的,因为极有可能算重。

那么不妨把不合法路径分为两类,令上面的直线为 \(a\),下面的直线为 \(b\),于是就可以根据一条不合法路径第一次碰的线的编号来区分了。这时候只需要找出其中一类怎么做就可以了,因为两类的做法是对称的。

再给一个定义。如果一条不合法路径碰线的顺序为 \(abbaab \ldots\),则记为 ABAB,即把连续的相同字母合并。

然后再放图。

现在只对以 A 开头的路径分析。

还是考虑翻折,把一条不合法路径沿直线 \(a\) 翻折,那么得到了新起点以及方案数,如图中粉色线。但是可以发现,如果翻折后的路径在 \(y\) 轴方向延伸地过长,翻折回来的时候就会先碰到直线 \(b\),再碰到直线 \(a\),如图中的青色线。这时候就要把这些路径再加回来,也就是把 BA 开头的路径加回来。

那么 BA 开头的路径怎么算呢?依然是翻折,考虑将一条这样的路径先沿直线 \(b\) 翻折,再沿直线 \(a\) 翻折,于是又得到了新的起点。但是类似的,可以发现这样会多算 ABA 开头的路径……

进而,在算 ABA 的时候会多算 BABA;在算 BABA 的时候会多算 ABABA……

不过可以发现,这个过程是有尽头的!因为每次的新起点 \((x,y)\) 会距离 \((0,0)\) 越来越远,直到 \(x > n \lor y > m\) 的时候就会结束,因为这时候就不存在任何满足条件的路径了。

注意到每次距离 \((0,0)\) 的相对位置至少增加 \(1\),所以复杂度是 \(O(n)\) 量级的,可以感性理解。

然后再回到这个题,发现事情远远没有那么简单()

先不考虑上面那个东西和这个题有什么关系。从题本身出发。

容易注意到 \(0 \le x_{i,j} \le m\)\(x_{i,j} < x_{i,j+1}\),而矩阵宽度正好为 \(m\),所以一行中的数一定是严格单增且只有一个数字不出现。所以可以这么 dp,设 \(f_{i,j}\) 为前 \(i\) 行,数字 \(j\) 不出现的方案数。转移考虑如何可以满足 \(x_{i,j} < x_{i-1,j+1}\) 的限制,有:

\[f_{i,j} = \sum _{x=0} ^{j+1} f_{i-1,x} \]

可以发现这个式子实际上就是算前缀和,所以可以转化为:

\[f_{i,j} = f_{i-1,j+1} + f_{i,j-1} \]

把这个转移拍到坐标系上,可以发现就是下图的合法路径条数。

然后再把斜线掰直,并将第 \(i\) 行的点右移 \(i\) 格;注意到最左边的向上的线掰不动,所以需要新建点,拆成向上向右两条线。于是就变成了我们想要的形式,也就是最上面那个图。

终点坐标为 \((n+m+1,n)\),两条直线分别为 \(y=x+1\)\(y=x-(m+2)\)

submission

天依宝宝可爱!

posted @ 2025-08-19 09:51  little__bug  阅读(12)  评论(0)    收藏  举报