阶乘、排列、组合
阶乘
x ! = Π i : 1 x i x! = \Pi_{i:1}^xi x!=Πi:1xi 。特殊情况0的阶乘是1。
排列
排列 P n m P_n^m Pnm,从n个不同元素中取出m(m≤n)个元素,按照一定的顺序排成一列。第一个元素有n种选择,第二个元素有n-1种选择, ⋯ \cdots ⋯
P n m = Π i : n − m + 1 n i = n ! ÷ ( n − m ) ! P_n^m = \Pi_{i:n-m+1}^ni= n!\div (n-m)! Pnm=Πi:n−m+1ni=n!÷(n−m)!
组合
C n m C_n^m Cnm 从n个不同的元素中,任取m(m≤n)个元素为一组。m个元素的顺序有m!种。故:
P n m ≡ C n m × m ! P_n^m \equiv C_n^m \times m! Pnm≡Cnm×m!
多数组合
以求单词的异构词为例。cnt记录26个字母的出现次数。则异构词的数量:
t o t a l [ x ] = ∑ i : 0 x − 1 c n t [ i ] total[x]=\sum_{i:0}^{x-1}cnt[i] total[x]=∑i:0x−1cnt[i]
异构词的数量 = Π i : 0 26 C t o t a x [ 26 ] − t o t a l [ i ] c n t [ j ] 异构词的数量=\Pi_{i:0}^{26}C_{totax[26]-total[i]}^{cnt[j]} 异构词的数量=Πi:026Ctotax[26]−total[i]cnt[j]
就是每个字符的组合相乘。
封装类
template<class T >
class CFactorial
{
public:CFactorial(int n):m_res(n+1){m_res[0] = 1;for (int i = 1; i <= n; i++) {m_res[i] = m_res[i - 1] * i;}} T Com(int iSel, int iCanSel) {return m_res[iCanSel] / m_res[iSel]/ m_res[iCanSel - iSel];}T Com(const vector<int>& cnt) {T biRet = 1;int iCanSel = std::accumulate(cnt.begin(), cnt.end(), 0);for (int j = 0; j < cnt.size(); j++) {biRet *= Com(cnt[j], iCanSel);iCanSel -= cnt[j];}return biRet;}vector<T> m_res;
};
帕斯卡法则及容斥原理
【数学归纳法 组合数学】容斥原理
封装类
template<class Result = C1097Int<> >
class CCombination
{
public:CCombination(){m_v.assign(1, vector<Result>(1,1));}Result Get(int sel, int total){assert(sel <= total);while (m_v.size() <= total){int iSize = m_v.size();m_v.emplace_back(iSize + 1, 1);for (int i = 1; i < iSize; i++){m_v[iSize][i] = m_v[iSize - 1][i] + m_v[iSize - 1][i - 1];}}return m_v[total][sel];}
protected:vector<vector<Result>> m_v;
};
阶乘求组合,初始化时:时间复杂度O(n),查询时:时间复杂度O(3)。
帕斯卡法则求阶乘,初始化时:时间复杂度O(nn),查询时:时间复杂度O(1)。
阶乘求组合用的乘法,帕斯卡法则用的加法,乘法比加法复杂。
题解
排列、组合、多数组合 |
---|
【归并排序】【图论】【动态规划】【 深度优先搜索】1569将子数组重新排序得到同一个二叉搜索树的方案数 |
【数学 排列组合】1643. 第 K 条最小指令 |
【数学】【组合数学】1830. 使字符串有序的最少操作次数 |
【树 图论 阶乘 组合 深度优先搜索】1916. 统计为蚁群构筑房间的不同顺序 |
【多数组合 数学 字符串】2514. 统计同位异构字符串数目 |
容斥原理 |
---|
【状态压缩 容斥原理 组合数学】3116. 单面值组合的第 K 小金额 |
其它 |
---|
【动态规划】C++ 算法458:可怜的小猪 |
【动态规划】【组合数学】【C++算法】920播放列表的数量 |
【深度优先搜索】【组合数学】【动态规划】1467.两个盒子中球的颜色数相同的概率 |
【动态规划】【组合数学】1866. 恰有 K 根木棍可以看到的排列数目 |
【动态规划】【前缀和】【分组】2338. 统计理想数组的数目 |
[组合数学]LeetCode:2954:统计感冒序列的数目 |
【组合数学】2842. 统计一个字符串的 k 子序列美丽值最大的数目 |
扩展阅读
视频课程
有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
相关下载
想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653
我想对大家说的话 |
---|
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。