乘法原理
乘法原理处理的是“分步骤完成一件事”:每一步有多少种选择,总方案数就把每一步的选择数乘起来。
一句话算法
乘法原理处理的是“分步骤完成一件事”:每一步有多少种选择,总方案数就把每一步的选择数乘起来。
问题模型
如果完成一件事必须依次完成
第 1 步 -> 第 2 步 -> ... -> 第 k 步
并且:
- 第
步有 种选择。 - 第
步在任意第 步选择后都有 种选择。 - …
- 第
步在前面步骤确定后都有 种选择。
那么总方案数是:
“乘法原理”
完成一个对象需要连续做若干个步骤,且每个完整方案都能唯一拆成这些步骤的选择,则总方案数等于各步骤选择数的乘积。
核心直觉
乘法原理不是“看到两个数就乘”,而是“走一条决策树”。
例如先从集合
A: a1, a2, a3
B: b1, b2
每个
a1 -> b1, b2
a2 -> b1, b2
a3 -> b1, b2
共有:
个有序对。
这
与加法原理的区别
加法原理是“分类”:做法属于哪一类。
乘法原理是“分步”:一个完整做法由哪些步骤组成。
| 原理 | 判断问题 | 关键词 |
|---|---|---|
| 加法原理 | 这件事可以分成哪些互斥类别? | 或者、分类、选一种 |
| 乘法原理 | 这件事要经过哪些连续步骤? | 先后、每一步、同时确定 |
例如:
- 从红球或蓝球中任选一个:分类,用加法。
- 先选一个红球,再选一个蓝球:分步,用乘法。
算法步骤
解决乘法原理计数题时,可以按下面四步做。
- 定义完整方案:先说清楚一个答案长什么样。
- 拆成步骤:把一个完整方案拆成若干个必须依次确定的选择。
- 计算每步选择数:注意后一步的选择数是否依赖前一步。
- 相乘:若每个完整方案都被唯一表示,直接乘起来。
如果后一步选择数会随前一步不同而变化,就不能简单写成固定乘积,需要分类后再乘:
算法证明
两步情况
设第一步选择集合为
完整方案是一个有序对:
对每个固定的
多步情况
把前
种方案,每种方案后面都能接
因此多步乘法原理成立。
复杂度分析
乘法原理本身是计数工具,不是固定算法。
- 若只计算公式,时间复杂度通常是
,其中 是步骤数。 - 若答案很大,需要使用高精度或在模意义下计算。
- 若每一步选择数依赖前面状态,可能需要动态规划或搜索,不再只是简单相乘。
代码实现
本文不提供代码模板。乘法原理通常直接出现在推导中,真正需要模板的场景会落到排列、组合、动态规划或快速幂等具体算法上。
测试用例
有序对计数
集合:
A = {a1, a2, a3}
B = {b1, b2}
从
排队问题
有
第一个位置有
密码问题
一个长度为 0..9,允许重复。
每一位都有
应用分类详解
乘法原理的本质是“一个方案由多个独立步骤拼成”。看到题目要求按位、按位置、按阶段依次确定对象时,应优先尝试乘法原理。
一、位置填充
典型模式: 若干个位置,每个位置填一个对象。
识别信号: 排队、座位、密码、字符串、路径每一步选择。
核心建模: 第
| 应用场景 | 经典题目 | 核心思路 |
|---|---|---|
| 密码数量 | 基础计数题 | 每一位独立选择 |
| 全排列 | 本书排列组合章节 | 位置选择数依次为 |
| 固定长度字符串 | 字母表计数 | 每个字符位置有固定选择数 |
二、对象组合成有序结构
典型模式: 一个答案是若干部分拼成的有序结构。
识别信号: 有序对、三元组、坐标、边的两个端点。
核心建模: 每一部分分别确定,完整结构由这些选择唯一决定。
三、递归分步
典型模式: 当前选一个对象后,剩余问题规模减少。
识别信号: “先选一个”“剩下的问题相同”“每次少一个”。
核心建模: 得到递推式,例如全排列:
最终得到:
四、概率中的样本空间
典型模式: 多次实验,每次实验有若干种结果。
识别信号: 掷骰子、抛硬币、抽牌顺序、随机字符串。
核心建模: 样本空间大小由每次实验结果数相乘得到。例如抛
经典例题
1. 不同人的排队数量
种排法。它是乘法原理最直接的应用。
2. 固定长度密码数量
长度为
3. 棋盘坐标数量
一个
参考
- 本书排列组合章节:
math/combinatorics/combinatorics/index.md - 本书加法原理章节:
math/combinatorics/rule_of_sum/index.md