什么是计数?
车牌号里的每一个序位数,都是从26个英文字母和10个阿拉伯数字里选取出来,然后按照约定好的顺序和规则去排列成一串号码。想求出都能排列出多少种可能,计算的这个过程就叫计数。
为什么要学习计数原理?
就类似上面的车牌案例,你要是一个一个数,从头到位的遍历出来,那确实不用什么学什么计数原理了,但是那样会很低效。或者说如果需要计数的范围很大,用一个一个数的方式本身就无法实现。那么学习计数原理就可以帮你高效地计算出全部可能排列的总数字。
计数原理要学什么?
主要是两类基本的计数原理,和一种特殊规则:
- 两类:
- 分类加法计数
- 分步乘法计数
- 特殊:
- 排列数和组合数
计数原理的研究范围:
如何采用最高效的方式去不重复、不遗漏地数清所有可能的情况。
分类加法计数(加法原理)
如果一个事件有多种互相独立的选择,且每种选择的方案数是已知的,那么总的方案数就是各种选择的方案数之和。
如果完成一件事有n类方法,且这n类方法互不重叠,那么完成这件事共有n1 + n2 + ... + n,共 n 种方法。
属于“或”、“分类”的关系。几类方案是相互独立的,选择任何一类都能完成任务。
例子:从北京到上海,可以坐火车(3个车次)或坐飞机(2个航班)。那么总共有 3 + 2 = 5 种走法。
分步乘法计数(乘法原理)
如果一个事件需要分步完成,且每一步的方案数是已知的,那么总的方案数就是每一步方案数的乘积。
如果完成一件事需要分n个步骤,且每个步骤有不同的方法数,那么完成这件事共有n1 * n2 * ... * n,共 n 种方法。
属于“与”、“分步”。所有步骤必须依次完成,缺一不可。
例子:从北京经上海到广州,先从北京到上海有3种走法,然后从上海到广州有4种走法。那么总共有 3 × 4 = 12 种走法。
总结:
- 区分问题属于分类还是分步很关键。
- 分类类似 或(OR) 的关系;
- 分步类似 且(AND) 的关系;
阶乘
在学习排列数之前,先来了解阶乘和递归。
阶乘函数(符号:!)的意思是把逐一减小的自然数序列相乘。例如:
1! = 1
4! = 4 × 3 × 2 × 1 = 24
7! = 7 × 6 × 5 × 4 × 3 × 2 × 1 = 5040
阶乘的特点:
-
增长很快!
⚠️ 在编程中,如果某算法的运算量是阶乘增长关系,那么通常被认为是“不合格”的算法(如旅行商问题的暴力解法);
阶乘和递归的关系:
要计算一个阶乘的值,我们可以用上一个阶乘的值:
比如我们要求 4!= ?
假设我们不知道4!这种运算要怎么求?我们只知道一个规律,要计算一个阶乘的值,我们可以用上一个阶乘的值。
可以先问:4! = 4* 3!,
在问:3! = 3* 2!,
在问:2! = 2* 1!,
在问:1!= ?
1!= 1, 这个是基准了,不用在向下追问了。那么就可以以此类推地回溯回去了。
2!= 2 * 1 = 2,
3!= 3 * 2 = 6,
4!= 4 * 6 = 24;
最后通过回溯得到答案。
递归就类似是阶乘运算,换一下量词,是不是很类似呢?
假设我们不知道某个方法要怎么求?我只知道一个规律,要计算一个方法的值,可以用上一个方法的值。
手算的递归,是你在纸上记录了递归的层级变化,最后得出结果。而计算机的递归是计算机的寄存器帮忙存储了层级变量,最后累加得出结果。
排列数
排列是研究对象在特定顺序下的安排方式。例如,从 4
个元素中选出 2
个,有多少种不同的排列方式?
比如,{a,b,c,d} 四个元素,你每次取2个出来,可以摆多少种?
n=4,
m=2,
可以想象一下,m是两个位置:( ) , ( ) 在这两个位置需要不重复的摆放一次各个元素,排序的过程类似编程的冒泡算法(一种处理顺序(排列)的简单算法)。
ab,ac,ad
ba,bc,bd
ca,cb,bd
da,db,dc
可以摆12种。
要从n个元素中取出m个(m ≤ n)元素,需考虑元素的顺序,称为从n个元素中取出m个元素的排列。 ,比如 密码“123”和“321”是完全不同的。
排列的个数用 P(n, m) 表示,
计算公式为:$$ P(n, m) = \frac{n!}{(n-m)!} $$
组合数
组合是研究对象在不考虑顺序的情况下,有多少种选择方式。例如,从 4
个元素中选出 2
个,有多少种不同的组合方式?
比如,{a,b,c,d} 四个元素,你每次取2个出来,可以摆多少种?
n=4,
m=2,
可以想成,m是两个位置:( ) , ( )
ab,ac,ad
ba,bc,bd
ca,cb,cd
da,db,dc
可以摆6种。
要从n个元素中取出m个(m ≤ n)元素,不考虑元素的顺序,称为从n个元素中取出m个元素的组合。,比如 组队: 从10个人中选出3个人组成一个委员会。队伍 {A, B, C} 和队伍 {C, B, A} 是同一个队伍。
总结:排列关心“谁在什么位置”;组合只关心“谁在里面”。
组合的个数用C(n, m)表示,
计算公式为:$$ C(n, m) = \frac{ n! } {(m! * (n-m)!)} $$
能区分一个问题是分类、分步、排列数、组合数,并且会套用相关公式计算出结果,已经算是入门了,属于一个合格的工具应用者了。
如果用编程算法来理解组合数,可以用回溯算法来生成 {a, b, c, d} 中所有 2 元素组合,如下是大致的每一步。
元素:{a,b,c,d},取所有2个元素组合。
第一次:a
将ab,ac,ad存储;
第二次:b
将bc,bd存储;
第三次:c
将cd存储;
第四次:d
无法形成长度为2的组合,退出。
ps:可以让AI生成一个算法,然后借助调试工具去理解这个过程,因为这个算法涉及到递归,纯人脑去理解递归是困难的,因为用人脑去模拟电脑的多个寄存器的存储状态,以及各轮的运算过程的变化,显然有点超负荷╮(╯▽╰)╭。
如何从模型推理出公式?
假设我们并没有排列P(n,m)、C(n,m)公式,那么我们怎么能根据已知的规律和模型,自己推导出一个普遍性公式呢?
todo
利用二项式定理求未知
到这里,你不光能计数,你还能预测数!
作用:
- 展开多次多项式
二项式定理描述了$ (x+y)^n $ 的展开式;
- 杨辉三角里系数和组合数的关系?
总结:不管是求组合数公式C(n, m),还是杨辉三角的系数规律,都只能求出一个总数,但是并不能具体给出你组合的数列。
要生成所有具体的、明确的组合,我们需要自己编程或者调用别人的算法去实现(如上述的编程算法)。
我用自己的语言描述了分类加法计数概念、分类乘法计数概念。
组合数和排列数概念,以及他们两个的区别。
二项式公式的作用。