数学基础-组合数学

排列数

定义

\(n\) 个不同元素中任取 \(m(n,m\in\mathbb{N}, m\le n)\) 个元素按照一定顺序排成一列,叫做从 \(n\) 个不同元素中取出 \(m\) 个元素的一个排列;从 \(n\) 个不同元素中取出 \(m\) 个元素的所有排列的个数,叫做从 \(n\) 个不同元素中取出 \(m\) 个元素的排列数,记作 \(A_n^m\)

计算公式

排列数的计算公式如下:

\[A_n^m=n(n-1)(n-2)...(n-m+1)=\frac{n!}{(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\)

计算公式

组合数的计算公式如下:

\[C_n^m=\frac{A_n^m}{m!}=\frac{n!}{m!(n-m)!} \]

其中,\(n!=\prod_{i=1}^{n}i\)

对称性

\[C_n^m=C_n^{n-m} \]

递推公式

\[C_n^m=C_{n-1}^{m-1}+C_{n-1}^m \]

三种实现方法

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\) 较少的情况。

posted @ 2024-08-13 14:41  catting123  阅读(95)  评论(0)    收藏  举报