组合数学学习笔记
其实只是没什么写题的心情,也不想摆,于是就来做一些组合计数的题,然后记录在这里...
基础知识
1.加法原理与乘法原理
加法原理:
如果一件做一件事的方法可以分为$n$个互不相同的类,并且其中的第$i$类有$m_i$种方法
那么完成这件事一共有$\sum\limits_{i = 1}^n m_i$种方法
乘法原理:
如果一件事要分$n$步,并且其中的第$i$步有$m_i$种方法
那么完成这件事一共有$\prod\limits_{i = 1}^n m_i$种方法
2.无重复的排列组合
排列:
从$n$个元素中,有序地取出$m$个元素称作$n$个数中取$m$个数的排列
记为$P_n^m$,或者$A_n^m$
由乘法原理,可以得到$P_n^m = \frac{n!}{(n - m)!}$
组合:
从$n$个元素中,无序地取出$m$个元素称作$n$个数中取$m$个数的组合
记做$C_n^m$,并且有$C_n^m = P_n^m * \frac{1}{m!} = \frac{n!}{m!(n- m)!}$
3.斯特林数
第一类斯特林数:
把$n$个不同的小球放进$m$个相同的圆排列,记为$s(n, m)$
$s(n + 1, m) = s(n, m - 1) + n * s(n, m)$
第二类斯特林数:
把$n$个不同的小球放进$m$个相同的盒子,记为$S(n, m)$
$S(n + 1, m) = S(n, m - 1) + m * S(n, m)$
4.二项式定理
$$(a + b)^n = \sum\limits_{i = 0}^n a^i b^{n - i} \binom{n}{i}$$
常用的二项式定理的其他形式:
$$(1 + 1)^n = 2^n = \sum\limits_{i = 0}^n * \binom{n}{i}$$
$$(1 - 1)^n = 0 = \sum\limits_{i = 0}^n (-1)^i * \binom{n}{i}$$
$$(2 - 1)^n = 1 = \sum\limits_{i = 0}^n 2^i * (-1)^{n - i} * \binom{n}{i}$$
$$(2 + 1)^n = 3^n = \sum\limits_{i = 0}^n 2^i * \binom{n}{i}$$
$$(1 + x)^n = \sum\limits_{i = 0}^n x^i * \binom{n}{i}$$
5.卡特兰数
对于给定的长为$n$的入栈序列,对应的可能的出栈数列的方案数
记做$C_n$
$C_n = C(2n, n) - C(2n, n - 1)$
$C_n = \frac{C(2n, n)}{n + 1}$
$C_n = C_{n - 1} * \frac{4n - 2}{n + 1}$
$C_n = \sum\limits_{i = 0}^{n - 1} C_i * C_{n - i - 1}$
6.容斥原理
公式有点难打,就不打了,应该都知道吧...
还有一个排斥原理,跟容斥原理很相近
(容斥原理其实是一种套路)
基础知识点差不多就这么多吧
只要你够强,什么都可以推出来的...
通过大量的练习来锻炼计数的能力吧
练习
部分题目是口胡的,如果发现不对请指出
大部分例题来源于《奥林匹克数学中的组合问题》,但是笔者或多或少有加强
T1.忐忑子集
如果$\{1, 2, ..., 9\}$的某个非空子集中所有元素之和是3的倍数,则称该子集为忐忑子集,试问有多少忐忑子集
爆搜一下就出来了
让我们先来看看数学组的方法:
如果$\{1, 2, ..., 9\}$的某个非空子集是忐忑子集,那么它的补集也是忐忑子集.
因此,我们只需考虑元素$\leqslant 4$的忐忑子集的个数.
只有1个元素的忐忑子集有$3$个
两数之和被3整除的充要条件是两个数被3除的余数只能是$(0, 0), (1, 2)$
而被$3$除余数为$0, 1, 2$的各有$3$个,因此含$2$个元素的忐忑子集的个数为$\binom{3}{2} + \binom{3}{1} * \binom{3}{1} = 12$
含有3个元素只可能是$(0, 0,0 ), (1, 1, 1), (2, 2, 2), (0, 1, 2)$,因此有${\binom{3}{1}}^3 + 3 * \binom{3}{3}$种方案
含有4元素同理只可能是$(0, 0, 1, 2), (1, 1, 1, 0), (0, 2,2,2), (1, 1, 2, 2)$,对应有$42$种方案
全集也是一个忐忑集合
因此最终有$2(3 + 12 + 30 + 42) + 1 = 175$种
非常漂亮的思路
下面我们再看看信息组的做法...
设$f[i][0 / 1/ 2]$表示在集合$\{1, 2..., i\}$中和模3的余数为$0, 1, 2$的子集有多少个
那么每次新增$i + 1$时,考虑选或不选转移即可
复杂度$O(n)$
#include <cstdio>
using namespace std;
int f[20][3];
int main() {
f[1][0] = 1; f[1][1] = 1;
for(int i = 1; i <= 10; i ++)
for(int j = 0; j <= 2; j ++) {
f[i + 1][j] += f[i][j];
f[i + 1][(i + 1 + j) % 3] += f[i][j];
}
printf("%d\n", f[9][0] - 1);
return 0;
}
简单多了,不是吗....
那么,我们能做到$O(1)$吗?答案是不可以的(其实是$O(\log n)$)
下面的$i / 3$默认下取整
当$i\;mod\;3 = 0$时,$f[i][0 / 1 / 2]$分别为$\frac{2^i + 2*2^{i / 3}}{3}, \frac{2^i - 2^{i / 3}}{3}, \frac{2^i - 2^{i / 3}}{3}$
当$i \;mod\;3 = 1$时,$f[i][0 / 1/ 2]$分别为$\frac{2^i + 2^{i / 3}}{3}, \frac{2^i + 2^{i / 3}}{3}, \frac{2^i - 2*2^{i / 3}}{3}$
当$i\;mod\;3 = 2$时,$f[i][0 / 1 / 2]$分别为$\frac{2^i + 2*2^{i / 3}}{3}, \frac{2^i - 2^{i / 3}}{3}, \frac{2^i - 2^{i / 3}}{3}$
快乐矩乘不就完事了
T2.运动会
安排$n$名同学参加$m$个运动项目,要求甲乙两同学不参加同一项目,且每个项目都有人参加,每个人只参加一个项目,求满足要求的不同方案数
补集转化
首先,$n$个不同的人放进$m$个相同的盒子的方案数为$S(n, m)$,即第二类斯特林数(百度百科?)
$n$个不同的人放进$m$个不同的盒子的方案数记做$f(n, m) = S(n, m) * m!$
暂时不考虑甲乙同学,那么有$f(n, m)$种可能
再考虑甲乙同学,把两个人看做一个整体,那么方案数有$f(n - 1, m)$种
最终答案即为$f(n, m) - f(n - 1, m)$
复杂度$O(n^2)$
T3.选集合
设集合$\{1, 2, ..., n\}$,选择此集合的两个子集$A, B$,满足$max(A) < min(B)$,问方案数
其实不怎么难的一道题?
首先,问题在于枚举什么然后计数,一直想着去枚举$A$然后去判断$B$,发现不太好做....
一种神奇的思路是枚举$|A \cup B|$,确定了并集大小后,相当于只要在并集内部放一块分隔板就行了
因此,总方案为$\sum\limits_{i = 2}^n (i - 1)C(n, i)$
然而后面的组合恒等式变形感觉更是神奇...$ = \sum\limits_{i = 1}^n iC(n, i) - \sum\limits_{i = 1}^n C(n, i)$
这里有一个组合恒等式,$kC(n, k) = nC(n - 1, k - 1)$,考虑选出单独的一个元素即可
$= n\sum\limits_{i = 1}^n C(n - 1, i - 1) - \sum\limits_{i = 1}^n C(n, i)$
$= n \sum\limits_{i = 0}^{n - 1} C(n- 1, i) - \sum\limits_{i = 0}^n C(n, i) + 1$
$ = n * 2^{n - 1} - 2^n + 1$
(对于$i C(n, i)$的求和感觉值得记忆)
另一种思路是枚举$max(A), min(B)$然后计数,和式的变换比起上面的方法难度小了许多
也许我们可以想想划分成$3$个集合甚至$m$个集合的情况.....
T4.正方体染色
你现在拥有$n$种颜色,你可以从中选出若干种颜色,将一个正方体的六个面染色,每面恰染一色,具有公共棱的两个面不共色,问不同的染色方案数
(这里,我们认为存在翻转和旋转两种置换)
首先,我们是不会用超过$6$种颜色的,也不会少于$3$种颜色,因此,实际上只需要对$3, 4, 5, 6$进行计数就好了
只用3种颜色时,先考虑染3面,可以发现之后的所有面的颜色都被固定,因此一共有$C(n, 3) * 1$种
令上前右下后左面分别为$1, 2, 3, 4, 5, 6$面
只用4种颜色时,先染好$1, 2, 3$面,假定它们的颜色为$a, b, c$,那么第$4$面有$a, d$两种选择
选择$a$时,$5, 6$有两种不同的方案,选择$d$时,$5, 6$只有一种方案
但是,我们发现每种方案都被我们统计了两次(比如开局$a, b, c$和$a, c, b$就有一个重复的方案)
因此,最终方案数为$C(n, 4) * C(4, 3) * 3 * \frac{1}{2} = C(n, 4) * 6$种方案
使用5种颜色时,随便染好5不相同的面后,剩下的一面一定会和对面相同
因此,相当于我们挑一组对面出来,染一种颜色后,剩下4面再4染色
但是要去重,可以发现每组对面对应的方案都是重叠的,只要对一组对面计数即可,剩下4面也要注意不重叠
剩下4面不重叠的方案数手动枚举下发现是3(4! / 4 / 2,/ 4表示旋转,/ 2表示翻转)
那么有$C(n, 5) * 5 * 3 = C(n, 5) * 15$种方案
使用6种颜色时,先染好$1, 2, 3$面,有$C(6, 3)$种方法
剩下3面可以自行安排颜色的顺序,因此有$6$种方法
考虑重复,对于一个正方体,前,后,左,右转都会被记1次
因此总共有$C(n, 6) * 6 * C(6, 3) / 4 = C(n, 6) * 30$种
从这里我们可以看出组合计数的分类讨论堪称各种脑洞展开.....
其实我们可以选择用电脑来统计,反正有电脑就是能任性啊......
T5.解方程(一)
求解不定方程$x_1 + x_2... + x_k = n$的方程组的非负整数解的组数
我们可以认为我们有$n + k - 1$个空,$k - 1$个板子随意地插入到其中
特别的,$0$号板子在最前面,$k$号板子在最后面(这两块板子被固定了位置)
那么,我们可以认为$p_i - p_{i - 1} - 1$代表了原方程的$x_i$,其中$p_i$表示第$i$块板子的位置
不难发现,这种办法与原问题存在一一映射的关系
T6.解方程(二)
求解不定方程$x_1 + x_2... + x_k = n$的方程组的非负整数解的组数
其中$x_i \geqslant a_i$
嗯.......跟上面其实没有很大差别
令$x_i' = x_i - a_i$,那么$x_i' \geqslant 0$
代入到原方程,那么$x_1' + x_2' + ... + x_k' + a_1 + a_2 + ... + a_k = n$
得到一个新方程$x_1' + x_2' + ... x_k' = n - a_1 - a_2 ... - a_k$
跟上面回到了一个问题
T7.解方程(三)
求解不定方程$x_1 + x_2... + x_k = n$的方程组的非负整数解的组数
其中$x_i \leqslant a_i$
嗯.......其实也没什么太大区别
上面的能$O(n)$,这个要$O(2^n)$而已......
考虑使用容斥原理
那么,转化条件后,只要求出一些$x_i \geqslant 0$,一些$x_i \geqslant a_i$,然后用全集减去就好啦
接连3道都是套路题呢......