组合数学汇总

阶乘、排列、组合

阶乘

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:nm+1ni=n!÷(nm)!

组合

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! PnmCnm×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:0x1cnt[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++**实现。

  • 106
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 35
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闻缺陷则喜何志丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值