
第三十九课:数学与逻辑②------阶乘、排列数与组合数:公式到底从哪里来?
上一课我们解决了一个最重要的问题:
换一下顺序,算不算一种新的结果?
-
不算 → 组合
-
算 → 排列
今天我们继续向前走一步,把三个非常重要的数学工具真正搞明白:
重点不是让大家死记公式,而是让同学们知道:
这些公式不是天上掉下来的,而是"一步一步数出来的"。
一、今天的故事:小明要组织一场颁奖典礼
班里有5位同学:
A B C D E
老师准备颁发三个奖项:
🥇 冠军
🥈 亚军
🥉 季军
问题来了:
从5个人中选出3个人,并分别获得冠军、亚军、季军,一共有多少种可能?
我们先不用公式。
二、第一步:冠军有几种选择?
冠军可以是谁?
A
B
C
D
E
一共有:
5
种。
三、第二步:亚军有几种选择?
假设冠军已经是A。
那么剩下:
B C D E
所以亚军有:
4
种选择。
四、第三步:季军有几种选择?
假设:
冠军:A
亚军:B
那么只剩:
C D E
所以季军有:
3
种选择。
因此:
5×4×3=60
答案:
60
这就是排列。
五、于是我们发现了排列数公式
从5个人中选3个人排列:
如果是:
从n个人中选m个人排列
那么:
第1个位置:n种
第2个位置:n-1种
第3个位置:n-2种
......
第m个位置:n-m+1种
所以:
这就是排列数。
六、但是还有一个神奇的东西:阶乘!
刚才我们看到:
这个东西在数学中有一个专门的名字:
读作:
5的阶乘
定义:
例如:
3!=3×2×1=6
4!=4×3×2×1=24
5!=5×4×3×2×1=120
6!=6×5×4×3×2×1=720
七、为什么阶乘这么重要?
因为:
阶乘其实就是"把所有东西排一遍"的方法数。
例如:
A B C
把3个人排成一列。
所有方法:
ABC
ACB
BAC
BCA
CAB
CBA
一共有:
6
而:
3!=6
所以:
3个人全部排列 = 3!
同理:
n个人全部排列=n!\boxed{n个人全部排列=n!}
八、一个特别重要的特殊情况:0!
孩子第一次看到:
0!
通常会问:
老师,0个东西怎么排列?
数学中规定了:
0! = 1
这个结论在组合公式中非常重要。
例如:
意思就是:
从n个东西里面一个都不选,只有一种方法。
那就是:
什么都不选
所以:
0! = 1
非常合理。
九、排列数如何改写成阶乘?
例如:
我们知道:
5!=5×4×3×2×1
所以:
因此:
所以一般公式:
十、为什么是 (n−m)!?
这个地方不要死记。
例如:
就是:
7×6×5
但是:
7!=7×6×5×4×3×2×1
后面多出来的是:
4×3×2×1 = 4!
而:
4 = 7−3
所以:
也就是:
十一、现在轮到组合登场
还是5个人:
A B C D E
如果我们只想:
选出3个人参加比赛。
那么:
ABC
和:
BAC
是同一种选择。
但是排列会把它们当成不同情况。
十二、排列比组合多了多少?
假设我们选中了:
A B C
这三个人可以怎么排列?
3!
种。
也就是:
6
种。
因此:
每一个"3人组合",在排列中会被计算3!次。
所以:
于是:
所以:
十三、组合公式终于来了!

十四、千万不要把两个公式混淆

十五、一个非常好用的"反推法"
看到:
可以这样想:
先把m个人选出来,再把这m个人全部排列。
例如:
如果先组合:
然后这2个人可以交换位置:
2!
所以:
也就是:
而:
完全一致。
十六、组合数的一个超级重要性质
观察:
和:
它们实际上相等。
为什么?
从5个人里面选2个人:
选中的2个人
等价于:
没有被选中的3个人
所以:
例如:
十七、这个性质为什么非常有用?
比如:
直接算:
看起来很吓人。
但利用:
可以变成:
于是只需要计算:
简单很多。
所以考试看到:
先看看:
m是不是很大?
如果很大,就把它变成:
n−m
十八、组合数还有一个神奇规律
看看:
分别是:
1, 5, 10, 10, 5, 1
于是:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
这就是我们曾经学习的:
杨辉三角
它和组合数有直接关系:
第n行的数字就是组合数
例如:
1 5 10 10 5 1
对应:
这也是为什么前面学习过的杨辉三角,和今天的组合数学是连在一起的。
十九、初赛中经常不让你真的计算
例如:
一个10个元素的集合有多少个子集?
这时候甚至不需要排列组合公式。
对于每一个元素:
选
不选
都有两种可能。
10个元素:
所以:
我们可以给出这一结论:n个元素的集合,每个元素都有"选/不选"两种可能,因此子集共有 2^n 个。
例如:
10个元素的集合中,恰好选择7个元素组成子集,有多少个?
就是:
所以如果问:
"10个元素集合中,7元素子集占所有子集的比例?"
就是:
这也是典型题型。
二十、再看一道竞赛中的经典题
甲、乙、丙三位同学选修课程。
有4门课程,甲选2门,乙、丙各选3门。
一共有多少种不同的选课方案?
这个题特别适合训练:
先分别计算,再使用乘法原理。
甲
4门中选2门:
乙
4门中选3门:
丙
4门中选3门:
三个人同时完成
甲有6种。
每一种甲的选择,乙有4种。
每一种甲乙组合,丙又有4种。
所以:
6×4×4=96
答案:
96
这就是采用了"组合数 和 乘法原理"思路。
二十一、C++中怎么计算组合数?
如果数据比较小,可以直接写一个阶乘函数:
#include <iostream>
using namespace std;
long long fact(int n)
{
long long ans = 1;
for(int i = 1; i <= n; i++)
{
ans *= i;
}
return ans;
}
long long C(int n, int m)
{
return fact(n) / fact(m) / fact(n - m);
}
int main()
{
cout << C(5, 3) << endl;
return 0;
}
输出:
10
二十二、但是这个程序有一个大问题
如果:
fact(100)
会发生什么?
100!
是一个极其巨大的数字。
long long 根本装不下。
所以在真正的算法题中,不能看到组合数就傻乎乎地计算:
n!
这就是信息学竞赛非常重要的一个意识:
数学公式正确,不代表直接写程序计算公式就是正确的算法。
以后我们会学习:
-
杨辉三角求组合数
-
递推
-
取模
-
防止整数溢出
-
快速计算组合数
今天先基本建立数学基础。
二十三、初赛"看到题目"的快速判断模板
以后大家遇到类似题目,可以按照下面流程:
第一步:到底是在"选"还是"排"?
↓
需要考虑顺序吗?
↙ ↘
不需要 需要
↓ ↓
组合 排列
↓ ↓
C(n,m) A(n,m)
如果是全部排列:
如果是从n个中选m个排列:
如果只是从n个中选m个:
二十四、今天容易错的5个地方
错误1:把"选3个人"自动当组合
不一定。
选3个人当冠军、亚军、季军
是排列。
错误2:把"排队"自动当排列
也不一定。
选出的同学按照年龄从小到大排列。
顺序已经被规定了,本质上只是选择。
错误3:忘记 m!
排列和组合最核心的关系:
错误4:不会使用对称性
看到:
C_{100}^{97}
应该想到:
错误5:看到阶乘就直接写程序算
数学上可以写:
但程序中可能溢出。
所以:
公式是数学工具,算法是程序工具。
两者不能混为一谈。
二十五、课堂练习
练习1
4个人全部排队,有多少种排法?
答案:
4! = 24
练习2
7个人中选3个人参加比赛,有多少种选法?
练习3
7个人中选3个人,分别担任队长、副队长、秘书。
练习4
可以改写成什么?
答案:
练习5
可以写成阶乘形式吗?
可以:
练习6
等于什么?
根据:
所以:
二十六、今天的"知识地图"
把今天的知识串起来:
阶乘
│
n! = 全排列
│
┌───────┴────────┐
↓ ↓
排列 A 组合 C
│ │
考虑顺序 不考虑顺序
│ │
└──────┬─────────┘
↓
A(n,m)=C(n,m)×m!
再记住:

二十七、给同学们的最终记忆口诀
全部排,阶乘 n!;
选了还要排,排列 A(n,m);
只选不排,组合 C(n,m);
排列里面藏组合,差一个 m!。
更重要的是这一句:
先别急着套公式,先问:换个顺序,还是不是同一种结果?
这句话真正掌握以后,排列组合题就从"背公式"变成了"分析问题"。