数学基础-组合数学
排列数
定义
从 \(n\) 个不同元素中任取 \(m(n,m\in\mathbb{N}, m\le n)\) 个元素按照一定顺序排成一列,叫做从 \(n\) 个不同元素中取出 \(m\) 个元素的一个排列;从 \(n\) 个不同元素中取出 \(m\) 个元素的所有排列的个数,叫做从 \(n\) 个不同元素中取出 \(m\) 个元素的排列数,记作 \(A_n^m\)。
计算公式
排列数的计算公式如下:
其中 \(n!=\prod_{i=1}^{n}i\)。
组合数
从 \(n\) 个不同元素中任取 \(m(n,m\in\mathbb{N}, m\le n)\) 个元素组成一个集合,叫做从 \(n\) 个不同元素中取出 \(m\) 个元素的一个组合;从 \(n\) 个不同元素中取出 \(m\) 个元素的所有组合的个数,叫做从 \(n\) 个不同元素中取出 \(m\) 个元素的组合数,记作 \(C_n^m\)。
计算公式
组合数的计算公式如下:
其中,\(n!=\prod_{i=1}^{n}i\)。
对称性
递推公式
三种实现方法
1.递推公式/杨辉三角
根据组合数的递推公式 \(C_n^m=C_{n-1}^{m-1}+C_{n-1}^m\),用二维数组存储如下所示:
1 | |||||
---|---|---|---|---|---|
1 | 1 | ||||
1 | 2 | 1 | |||
1 | 3 | 3 | 1 | ||
1 | 4 | 6 | 4 | 1 | |
1 | ... | ... | ... | ... | 1 |
其中,\(f[n][m]\) 表示 \(C_n^m\)。
此方法的时间复杂度和空间复杂度均为 \(O(n^2)\),但其只需进行加法运算,且每次查询的时间复杂度为 \(O(1)\),总时间复杂度为 \(O(n^2+q)\)。此方法适用于 \(n\) 较小且查询次数 \(q\) 较多的情况。
2.计算所有 \(n!\) 及其乘法逆元 \((n!)^{-1}\)
根据计算公式 \(C_n^m=\frac{n!}{m!(n-m)!}\),用两个一维数组分别存储 \(i!\) 及其乘法逆元 \((i!)^{-1}\),即 \(fac[i]=i!, fac\_inv[i]=(i!)^{-1}\),时间复杂度和空间复杂度均为 \(O(n)\)。
查询时计算 \(C_n^m=fac[n]\times fac\_inv[m]\times fac\_inv[n-m]\%p\),时间复杂度为 \(O(1)\),总时间复杂度为 \(O(n+q)\)。此方法适用于 \(n\) 不太大且查询次数 \(q\) 较多的情况。
3.边乘边除
根据计算公式 \(C_m^n=\frac{(n-m+1)\times(n-m+2)\times...\times(n-1)\times n}{1\times2\times...\times(m-1)\times m}\),每次乘 \((n-m+i)\) 同时除 \(i\),防止答案过大上溢出错。可用双指针优化,分母能除则除尽。单次计算的时间复杂度为 \(O(m)\),空间复杂度为 \(O(1)\),对于 \(q\) 次查询,总时间复杂度为 \(O(q\times m)\)。此方法适用于 \(n\) 较大但 \(m\) 不太大且查询次数 \(q\) 较少的情况。