组合数&组合数取模(持续更新中)
排列组合及组合数取模
Part.1 组合数学
关于加法乘法原理
可以大概理解成计算方案时,互不影响的每一个“步骤”应作乘法,一个“步骤”的每一类“方法”应作加法。(摘自oi-wiki)
排列数 \(A_n^m\)
定义:从 \(n\) 个人中选 \(m\) 个人,这 \(m\) 个人有一定的位置顺序( \([1,2,3]\) 和 \([2,1,3]\) 不同)的方案数。
计算:
理解:
其实就是顺序枚举 \(m\) 个位置,然后第一个位置有 \(n\) 种选法,第二个位置有 \(n-1\) 种选法,以此类推,然后乘法原理乘起来就好了。
组合数 \(C_n^m\)
也写作: \(\binom{n}{m}\)
定义其实和排列类似,但是这里规定了选出来的没有顺序( \([1,2,3]\) 和 \([1,3,2]\) 等价)。
计算:
理解:
其实就是除以选出来的 \(m\) 个数的全排列。
递推式:
其实就是选或不选这个元素。
关于性质:建议自行查看oi-wiki。
关于插板法:自己去文化课学去qwq。
第一类斯特林数
将 \(n\) 个两两不同的元素分成 \(m\) 个互不区分的非空轮换的方案数。
关于轮换:其实就是圆排列,也就是将序列串成环之后的不同的方案数。
举个栗子:\([1,2,3]\) 和 \([3,1,2]\) 是等价的,但 \([1,2,3]\) 和 \([1,3,2]\) 不是等价的。
递推式:
插入一个新元素时,有两种放法:
- 新开一个轮换。
- 放入任何一个已有元素的前面。
所以加起来就得到了这个式子。
生成函数和通项公式:不讲。。。
第二类斯特林数
定义:将 \(n\) 个两两不同的元素分成 \(m\) 个互不区分的非空集合的方案数。
和一类的区别就在于一类只是不允许出现轮换,而二类则没有任何顺序(集合的基本性质之一:无序性)。
递推式:
插入一个新元素时,有两种放法:
- 新开一个集合。
- 放入任何一个已有集合的前面。
生成函数和通项公式:不讲。。。
经典用途:组合数拆 \(x^n\)。
先给结论:
另一种更常见的写法(组合数写法):
证明(组合意义法):左边可以理解成有 \(n\) 个互不相同的小球放入 \(x\) 个不互相同的盒子里的方案数。
那可以枚举哪些箱子是有球的(\(k\) 个),所以可以先将 \(n\) 个小球划分成 \(k\) 个集合(\(n \brace k\)),再在 \(x\) 个箱子里选出 \(k\) 个箱子来承载这些小球(\(A_k^x\))。
容斥原理
其实作集合题的时候应该就遇到过了吧,就是有三个项目,说同时报哪两个的有多少人,三个的有多少人,一个的有多少人。
也就是:
\(|A \cup B \cup C|=|A|+|B|+|C|-|A \cap B|-|B \cap C|-|A \cap C|+|A \cap B \cap C|\)

一般形式就是:
简单理解一下其实就差不多,下面是证明方法:
假设我们现在有一个元素 \(x\),那么包含 \(x\) 的集合有:\(T_1,T_2,T_3,\cdots,T_m\)。
设出现次数为 \(f(x)\)
\( \begin{aligned} f(x)&=\sum_{k=1}^{m}{(-1)^{k-1}\sum_{a_i<a_{i+1}}{\left| \bigcap_{i=1}^{k}{T_{a_i}} \right|}}\\ &=\sum_{k=1}^{m}{(-1)^{k-1}\binom{m}{k}} \\ &=\binom{m}{0}-\sum_{k=0}^{m}{(-1)^k \binom{m}{k}} \\ &=\binom{m}{0}=1 \end{aligned} \)
关于第一步到第二步:先是枚举取并集的集合个数,而每个取并集的集合中都正好出现过一次 \(x\),所以每个个数都对应了 \(\binom{m}{i}\) 种方案。
由于每个元素只出现过一次,所以并起来正好就是全部的交集了。
一个常用的容斥方法:
以错位排序为例(对于一个 \(1\) ~ \(n\) 的排列 \(P\),\(\forall i \in [1,n], P_i \ne i\))
下文称 \(P_i=i\) 为匹配
注意到其实每一个位置都不匹配可以等价于所有的方案数减去至少有一个位置匹配的方案数(合法方案=所有方案-非法方案)。
所以设 \(f(x)\) 为至少有 \(x\) 个位置可以匹配(即钦定 \(x\) 个位置可以匹配)。
所以 \(f(x)=(n-x)!\binom{n}{x}\)(枚举哪几个可以匹配,其余位置随意排布)。
则我们可以把容斥原理更改一下(\(S_i\)表示\(P_i=i\)的方案数):
其实集合取交集本质上就是在钦定哪 \(x\) 个元素能够匹配的过程。
所以式子就变成了
而我们求的是非法方案数,现在要减回去。
即为所求。
其实可以进一步化简,但在这里就不化简了,感兴趣的可以自己推一下。
二项式反演
其实在这个专题理论上是用不上的,但是有一个题用到了,所以讲一下。
不过因为并不是主要内容,所以就只是粗略的讲一下。
注:二项式反演证明过程用到了较多的组合数性质,请熟悉了组合数的性质在来学习证明方法。
其实二项式反演和容斥原理还是比较像的。。。
我们设两个函数:\(f(n)\) 表示恰好使用 \(n\) 个元素构成某种结构方案数,\(g(n)\) 表示在 \(n\) 个元素中选出 \(i\) 个元素构成某种结构的方案数。
由 \(f\) 推 \(g\) 显然有:
则由 \(g\) 推 \(f\) 有:
上面由 \(g\) 推 \(f\) 的过程即为:二项式反演。
证明:
\( \begin{aligned} f(n) &=\sum_{i=0}^{n}{(-1)^{n-i}\binom{n}{i}g(i)} \\ &=\sum_{i=0}^{n}{(-1)^{n-i}\binom{n}{i}{\sum_{j=0}^{i}{\binom{i}{j}f(j)}}} \\ &=\sum_{j=0}^{n}{f(j)\sum_{i=j}^{n}{(-1)^{n-i}\binom{n}{i}{\binom{i}{j}}}} \\ \end{aligned}\)
由组合数性质得:
\(\begin{aligned} f(n)&=\sum_{j=0}^{n}{f(j)\binom{n}{j}\sum_{i=j}^{n}{(-1)^{n-i}\binom{n-j}{i-j}}} \end{aligned} \)
设 \(k=i-j\):
\(\begin{aligned} f(n)&=\sum_{j=0}^{n}{f(j)\binom{n}{j}\sum_{k=0}^{n-j}{(-1)^{n-j-k}\binom{n-j}{k}}} \\ &=\sum_{j=0}^{n}{f(j)\binom{n}{j}\sum_{k=0}^{n-j}{(-1)^{n-j-k}\binom{n-j}{n-j-k}}}\\ &=\sum_{j=0}^{n}{f(j)\binom{n}{j}[n-j=0]} (由组合数性质得) \\ &=f(n) \end{aligned} \)
\(Q.E.D.\)
Part.2 组合数学中的数论
中国剩余定理 crt
吃了这么多素菜(指组合数学),终于到了荤菜(指数论)了。
关于为什么讲中国剩余定理:因为 \(exLucas\) 需要使用中国剩余定理求,所以就先讲一下。
中国剩余定理用于解决同余方程组问题:
\( \begin{cases} x \equiv r_1 \pmod{m_1} \\ x \equiv r_2 \pmod{m_2} \\ x \equiv r_3 \pmod{m_3} \\ \vdots \\ x \equiv r_n \pmod{m_n} \end{cases} \)
如果直接理解较为困难,可以先学习拉格朗日插值,和中国剩余定理有异曲同工之妙。
我们可以把 \(x\) 构造成由 \(n\) 项构成得一个数,使得第 \(i\) 项只在模 \(m_i\) 时不是 \(0\),这样我们只需要把这一项的值与 \(r_i\) 同余即可啦。
所以我们的 \(x\) 就顺理成章的推出来了。
先用 \(n=3\)理解一下,设 \(q_i(x)\) 表示 \(x\) 在模 \(m_i\) 意义下,\(x\) 的逆元。
\(x=m_2m_3(q_1(m_2m_3))r_1+m_1m_3(q_2(m_1m_3))r_2+m_1m_2(q_3(m_1m_2))r_3 \pmod{m_1m_2m_3}\)
那么一般形式就是:
想必各位已经发现了吧,我们要求逆元,所以 \(m_i\) 必须两两互质!
扩展中国剩余定理 excrt
既然都将了中国剩余定理了,那就讲一下扩展的吧。
上文中我们提到了\(m_i\) 必须两两互质。
可是如果并不两两互质怎么办呢?
这就是扩展中国剩余定理的用处。
那我们到底怎么求解呢?
现在单拎出来两个方程考虑怎么求解。
\( \begin{cases} x \equiv r_1 \pmod{m_1} \\ x \equiv r_2 \pmod{m_2} \end{cases} \)
可以换一种写法
\(x=k_1m_1+r_1=k_2m_2+r_2\)
移项得:
\(k_1m_1-k_2m_2=r_2-r_1\)
这就是一个普普通通的不定方程了,可以使用裴蜀定理和扩展欧几里得算法求解。
设 \(d=gcd(k_1,k_2)\)
所以如果 \(r_2-r_1\) 不是 \(d\) 的倍数,就无解。
设 \(p_1=\frac{m_1}{d},r_2=\frac{m_2}{d}\),现在求解:
\(k_1p_1-k_2p_2=\frac{r_2-r_1}{d}\)
转化成而\(exgcd\)的形式:
\(y_1p_1+y_2p_2=1\)
假设使用扩展欧几里得我们求解出了 \(y_1,y_2\)。
那么就可以搞出 \(k_1,k_2\):
\( \begin{cases} k_1= \frac{r_2-r_1}{d}y_1\\ k_2= -\frac{r_2-r_1}{d}y_2 \end{cases} \)
所以 \(x=k_1m_1+r_1=\frac{r_2-r_1}{d}y_1m_1+r_1\)
现在解出了 \( \begin{cases} x \equiv r_1 \pmod{m_1} \\ x \equiv r_2 \pmod{m_2} \end{cases} \) 的解,但是该如何解出整个的方程组呢?
【定理】 如果 \(x^*\) 为\( \begin{cases} x \equiv r_1 \pmod{m_1} \\ x \equiv r_2 \pmod{m_2} \end{cases} \) 的有一解,则有:
这个怎么证呢?
其实只需要证明在 \([0,lcm(m_1,m_2))\) 中只存在一个解即可,现在假设该方程组有两个解 \(x,y(0 \le x \le y < lcm(m_1,m_2))\),那么:
\( \begin{cases} x \equiv r_1 \pmod{m_1} \\ x \equiv r_2 \pmod{m_2} \end{cases} \) \( \begin{cases} y \equiv r_1 \pmod{m_1} \\ y \equiv r_2 \pmod{m_2} \end{cases} \)
所以同时做差得:
\( \begin{cases} (y-x) \equiv 0 \pmod{m_1} \\ (y-x) \equiv 0 \pmod{m_2} \end{cases} \)
合并起来得到:\((y-x) \equiv 0 \pmod{lcm(m_1,m_2)}\)
由于 \(x, y\) 均小于 \(lcm(m_1,m_2)\),所以 \(y- x\) 小于 \(lcm(m_1,m_2)\),所以此时一定有 \(x=y\),证毕。
那所以算法的流程就是:
- 拎出来两个方程,然后解出一个解(或直接输出无解),记为 \(y\)
- 将 \(x \equiv y \pmod{lcm(m_i,m_{i-1})}\) 替换为新的方程。
- 重复以上步骤,最后的 \(y\),就是答案了。
卢卡斯定理 Lucas
我们常常会遇到一种题目,模数不是很大,但是组合数中的 \(n,m\) 却大的吓人。
这是就需要请出卢卡斯定理出山了。
出山之前我们先来三顾卢卡斯于数论之中。
【引理】 当 \(p\) 为质数时,有:
如何证明呢?
先拆开来看看:
这个 \(x^i\) 对于计算是不影响的(不固定),所以只看系数:
发现了吗,当 \(0 < i < p\) 时 \(i < p\) 且 \(p-i < p\)。
那这有什么用呢?
因为 \(p\) 是质数,这意味着分母是不可能把分子中的 \(p\) 约分掉的!
所以:当 \(0 < i < p\) 时:
把这个结论带回去,就可以得到:
证明完引理,现在来看一个这么个式子 \(\binom{n}{m} \pmod{p}\)
可以设 \(n=ap+b,m=cp+d\)。
所以:
这个式子有什么用呢?
因为 \(m\) 拆成的 \(cp+d\) 是具有唯一性的,又由于在 \((1+x)^n\) 和 \((1+x^p)^a(1+x)^b\) 这个多项式中的系数一定是一一对应同余的(下面有解释),所以两边 \(x^m\) 项系数同余,即:
关于为什么多项式中的系数一定是一一对应同余的,其实是多项式同余的概念。
化成一般形式就是卢卡斯定理了(\(p\) 为质数):
\(Q.E.D.\)
扩展卢卡斯定理 exLucas
由于一开始引理中就强调了 \(p\) 一定是质数,这也就体现出了卢卡斯定理的局限性(只能处理质数模数)。
那模数不是质数怎么办呢?
【引理】 设 \(p^k\) 为 \(m\) 的质因数分解,则 \(x \pmod{m}\) 的值等价于:
\( \begin{cases} y \equiv x \pmod{p_1^{k_1}} \\ y \equiv x \pmod{p_2^{k_2}} \\ y \equiv x \pmod{p_3^{k_3}} \\ \vdots \\ y \equiv x \pmod{p_c^{k_c}} \end{cases} \)
的解
证明:早在扩展中国剩余定理中我们就证明了该方程组的最小非负整数在 \([0,lcm(m_i,m_{i+1}))\) 中是唯一的,而所有模数的最小公倍数就是 \(m\),所以该方程组的解就是要求的 \(x \pmod{m}\)。
那现在就轻松多了,只需要求出:
那现在就考虑如何去求组合数模质数的若干次方的结果就好了。
现在我们回归最原始的式子:
即求:
如果 \(k=1\),那很好办了,直接求逆元就好了(虽然复杂度也爆了)。
那可以效仿该思路,使得 \(m!\) 和 \(p^k\) 互质就好了~
所以式子可以化成:
这样如果可以求出 \(\frac{n!}{p^x}\) 就可以开心的直接求逆元啦!
问题转化成了如何求解 \(\frac{n!}{p^x}\)
现在来把 \(n!\) 拆开看看:
\(n!=1\times 2\times 3\times\cdots\times p\times (p+1)\times\cdots\times n\)
如果学过分块,就会发现,其实这个阶乘可以以每个 \(p^k\) 的倍数拆成一个块,这些块在模 \(p^k\) 意义下是完全等价的。
\(n! \equiv 1\times 2\times 3\times\cdots\times p^k\times 1\times 2\times 3\times\cdots\times 2p^k\times\cdots\)
然后再把每个 \(p\) 的倍数中的一个 \(p\) 删去:
\(n! \equiv 1\times 2\times 3\times (p-1)\times (p+1)\times\cdots\times (p^k-1)\times 1\times 2\times 3\times\cdots\times 2(p^k-1)\times\cdots\)
那这样式子似乎就明了了,而删去 \(p\) 之后的值就变成了一个阶乘的形式。
\(p\times 2p\times 3p\times\cdots\times hp=p^hh!\)
所以:
可是这样就万事大吉了吗?
现在是成功将 \(p\) 剔除了,但是 \(\left \lfloor \frac{n}{p} \right \rfloor!\) 呢?
所以需要递归一下,设 \(f(n)=\frac{n!}{p^x}\),则:
现在求出了 \(f(n)\),不过还是有一点问题,那就是 \(p^x\) 未能求出,但是仔细观察一下原式子,后面乘的一坨里根本没有 \(p\),只有一开始被扔掉的 \(p^{\left \lfloor \frac{n}{p} \right \rfloor}\) 中有 \(\left \lfloor \frac{n}{p} \right \rfloor\) 个,所以设 \(g(n)\) 表示 \(\frac{n!}{p^x}\) 中的 \(x\)。
把这些函数带回原始式子得:
这样,算法全部完成。
End
呼~终于打完了。
持续更新中...

浙公网安备 33010602011771号