🏃

排列:顺序有关系的计数

接力赛换两个人跑位就是另一种安排——「排好顺序」的方法数,每个位置依次减 1,乘起来就是 A(n,k)。

💡 打个比方

学校 4×100 米接力,4 名选手的棒次(谁跑第几棒)就是「顺序」:小明跑第 1 棒是一种安排,小明跑第 2 棒是另一种——换两个人的位置,就是新的排列。这就是「顺序有关系」。

从 4 人(甲乙丙丁)里选 3 人当班长、副班长、宣传委员:第 1 个位置(班长)4 种选法,第 2 个位置 3 种(班长不能再用),第 3 个位置 2 种 → 4 × 3 × 2 = 24 种。数学上把「从 n 个里选 k 个按顺序排好」叫做排列,方法数记作 A(n,k),公式 A(n,k) = n × (n−1) × … × (n−k+1)(一共 k 个因子)。

把 n 个全部排成一列叫全排列,数 = n × (n−1) × … × 2 × 1,记作 n!(n 的阶乘)。3 个人排队 = 3! = 3 × 2 × 1 = 6 种。

术语:排列(Permutation:选出来还要排顺序,顺序有关系);A(n,k)(排列数:从 n 个里选 k 个排成一列,A(n,k) = n×(n−1)×…×(n−k+1),k 个因子);全排列 / 阶乘 n!(把 n 个全排好,n! = n×(n−1)×…×2×1,规定 0! = 1);棒次(接力赛跑第几棒)。

🖼️ 大图看明白

左边:接力棒次——换顺序就是新安排 第 1 棒 第 2 棒 第 3 棒 第 4 棒 甲 乙 丙 丁 甲 乙 丙 丁 乙 甲 丙 丁 交换前两名 同一批人、不同棒次 = 不同排列 右边:排列公式 & 全排列 排列 A(n,k):从 n 个里选 k 个排成一列 A(n,k) = n × (n−1) × … × (n−k+1),共 k 个因子 例:4 人选 3 个职位:4 × 3 × 2 = 24 种 每个位置少一人:4 种 → 3 种 → 2 种 全排列 n!:n 个全部排成一列 n! = n × (n−1) × … × 2 × 1 3 人排队:3! = 6 种;4! = 24;5! = 120 快速自检:顺序有关系吗? 职位不同(班长 ≠ 副班长)→ 排列 A 不分职位(2 人合影)→ 组合 C(下节课)

🧩 子任务 1:什么是排列——A(n,k) 每个位置少一人

🎯 小目标:理解「从 n 个里选 k 个排成一列」,会手推 A(4,3) = 24,记住公式 A(n,k) = n×(n−1)×…×(n−k+1)。

4 人(甲乙丙丁)选 3 人当班长、副班长、宣传委员。三个职位不一样:甲当班长、乙当副班长,和甲当副班长、乙当班长,是两种不同的安排——顺序有关系,所以用排列数 A(4,3)。

// 手推:一个位置一个位置填
第 1 个位置(班长):4 人选 1 → 4 种
第 2 个位置(副班长):剩 3 人选 1 → 3 种(班长不能再当)
第 3 个位置(宣传委员):剩 2 人选 1 → 2 种
→ A(4,3) = 4 × 3 × 2 = 24 种

// 一般公式:A(n,k) = n × (n−1) × … × (n−k+1),一共 k 个因子
A(4,3) = 4 × 3 × 2 = 24          // 3 个因子,从 4 降到 2
A(5,3) = 5 × 4 × 3 = 60          // 3 个因子,从 5 降到 3
A(10,2) = 10 × 9 = 90            // 2 个因子
A(4,4) = 4 × 3 × 2 × 1 = 24      // 选 4 个排 4 列 = 全排列 4!

// 两个约定:A(n,1) = n(只选 1 个排 1 列,就是选 1 个);A(n,n) = n!
✅ 小检查:① A(6,2) = ?② 公式里「k 个因子」指什么?第一个和最后一个因子各是什么?③ 5 人选 1 人当值日班长,有多少种选法?(这就是 A(5,1))
看看答案 ① 6 × 5 = 30。② 因子是从 n 开始连续递减的整数,共 k 个:第一个因子是 n,最后一个因子是 n−k+1。③ A(5,1) = 5 种——只排 1 列时,排列就退化成「选 1 个」。
易错:把 A(4,3) 写成 4 × 4 × 4 = 64——班长选定后,副班长不能再是同一人!「不重复」意味着每填一个位置,下一个位置的候选就少 1。

🧩 子任务 2:全排列——3! 与阶乘

🎯 小目标:理解全排列 n! = n×(n−1)×…×1,会枚举 3 人排队的全部 6 种,记住 1!~5! 的值。

3 个人(A、B、C)排成一排照相:第 1 位 3 种、第 2 位 2 种、第 3 位 1 种 → 3 × 2 × 1 = 6 种。把 3 个全部排好叫全排列,数写作 3!(读「3 的阶乘」)。动手枚举一遍,正好 6 种:

// 枚举 3 人全部 6 种站法(固定第 1 位,再排后面两位)
  A B C     A C B
  B A C     B C A
  C A B     C B A

// 阶乘速查表(常用值,建议记住前 5 个)
  1! = 1
  2! = 2
  3! = 6
  4! = 24
  5! = 120
  6! = 720
  7! = 5040

// 规定:0! = 1(先记住,后面 A(n,0) = 1 会用到它)
// 阶乘长得飞快:10! = 3,628,800;13! ≈ 62 亿,
// 已经超过 C++ int 上限(2,147,483,647 ≈ 21 亿)→ 大数要用 long long
✅ 小检查:① 4! = ?5! = ?② 5! − 4! = ?③ 5 人排队,规定 A 必须站第 1 位,有多少种排法?(提示:A 固定后,剩下 4 人怎么排?)
看看答案 ① 4! = 4×3×2×1 = 24;5! = 5×24 = 120。② 120 − 24 = 96。③ A 占死第 1 位,剩下 4 人任意排 → 4! = 24 种。
易错:把 5! 写成 5×5×5×5×5 = 3125——阶乘的因子逐个减 1:5×4×3×2×1 = 120。另一个坑:算 13! 用 int 会溢出(超过 21 亿),用 long long 才安全。

🧩 子任务 3:编程枚举全排列——三重 for + 不等式过滤

🎯 小目标:用三重循环 + if 过滤枚举 3 人全部 6 种排队,理解「过滤保证每个人只出现一次」。

思路:让 3 个位置都从 {A,B,C} 里独立选,一共 3×3×3 = 27 种组合;再用一个 if 把「同一个人占了两个位置」的 21 种过滤掉,剩下的 6 种恰好是 3! 。

// 枚举 A B C 三人全部 6 种排队
char p[3] = { 'A', 'B', 'C' };
int cnt = 0;
for (int i = 0; i < 3; i++)            // 第 1 位:3 人选 1
    for (int j = 0; j < 3; j++)        // 第 2 位:3 人选 1
        for (int k = 0; k < 3; k++) {  // 第 3 位:3 人选 1
            // 三个人两两不同,才算合法排队
            if (p[i] != p[j] && p[j] != p[k] && p[i] != p[k]) {
                cnt++;
                cout << cnt << ": " << p[i] << p[j] << p[k] << endl;
            }
        }
// 输出恰好 6 行 = 3!:
// 1: ABC   2: ACB   3: BAC
// 4: BCA   5: CAB   6: CBA
✅ 小检查:① 27 种组合里为什么有 21 种被过滤?② 如果漏写条件 p[i] != p[k],会输出哪种「有人重复」的排队?举个例子。③ 想枚举「3 人选 2 人排队」(A(3,2)),代码怎么改?
看看答案 ① 只要有一个位置和别人相同就被过滤,比如 A A B(第 1、2 位都是 A)、A B A(第 1、3 位都是 A)这类,共 21 种。② 漏写 p[i] != p[k] 后,第 1、3 位相同不再被拦,会输出 A B A(A 出现了两次)。③ 只留两层循环(i、j)+ if (p[i] != p[j]),输出 p[i]、p[j],共 A(3,2) = 3×2 = 6 种。
易错:if 里必须检查所有两两组合:(i,j)、(j,k)、(i,k) 三个条件一个都不能少。只查相邻位置(i≠j、j≠k)会漏掉「隔位重复」的 A B A。

🧩 子任务 4:编程算 A(n,k)——连乘循环

🎯 小目标:用循环计算 A(n,k)(连乘 k 个递减因子);会解涂色应用题「3 格涂 3 种不同色」。
// 计算 A(n,k):从 n 开始连乘 k 个「逐个减 1」的因子
int A(int n, int k) {
    int res = 1;
    for (int i = 0; i < k; i++)        // 乘 k 个因子:n, n-1, ..., n-k+1
        res *= (n - i);
    return res;
}
A(5,3) = 5 × 4 × 3 = 60
A(4,3) = 4 × 3 × 2 = 24
A(10,2) = 10 × 9 = 90

// 应用题:一排 3 个方格,用红/绿/蓝 3 种颜色涂,
// 每格 1 色且 3 格颜色互不相同,有多少种涂法?
// 第 1 格:3 种;第 2 格:2 种;第 3 格:1 种 → A(3,3) = 3! = 6 种
// 枚举:红绿蓝、红蓝绿、绿红蓝、绿蓝红、蓝红绿、蓝绿红
✅ 小检查:① A(10,3) = ?② 涂色题如果允许三格同色,有多少种?(提示:这题还是排列吗?)③ 循环里第 i 次(i 从 0 开始)乘的是哪个因子?用 n=5、k=3 验证。
看看答案 ① 10 × 9 × 8 = 720。② 允许同色时每格独立 3 种 → 3×3×3 = 27 种——位置还是「排」的,但没有「不能重复」的限制,就是普通的乘法原理,不再是排列。③ i=0 乘 5、i=1 乘 4、i=2 乘 3,合起来 5×4×3 = 60 = A(5,3) ✓。
易错:循环写成 for (int i = 1; i <= k; i++) res *= (n - i); 会从 n−1 开始乘,整组因子差一位,算出来是 (n−1)×(n−2)×…——第一个因子必须是 n 本身,所以用 n - i(i 从 0 开始)。

💻 完整代码:排列计算器(算 A(n,k),小 n 时枚举全排列)

// 输入:n, k(1 ≤ k ≤ n ≤ 13,结果用 long long 防溢出)
// 输出:① A(n,k) 的值 ② 若 n ≤ 3,把 n 个元素的全排列全列出来
// 示例:输入 4 3 → A(4,3) = 24
// 示例:输入 3 2 → A(3,2) = 6,并列出 3 的全排列 6 种
#include <iostream>
using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    long long res = 1;
    for (int i = 0; i < k; i++)      // 连乘 k 个递减因子
        res *= (n - i);
    cout << "A(" << n << "," << k << ") = " << res << endl;

    if (n <= 3) {                    // n 小就演示全排列
        char p[] = { 'A', 'B', 'C' };
        int cnt = 0;
        if (n == 1) {
            cout << "1: A" << endl;
        } else if (n == 2) {
            cout << "1: AB" << endl;
            cout << "2: BA" << endl;
        } else {                     // n == 3:三重循环 + 两两不等
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                    for (int m = 0; m < 3; m++)
                        if (i != j && j != m && i != m) {
                            cnt++;
                            cout << cnt << ": " << p[i] << p[j] << p[m] << endl;
                        }
        }
    }
    return 0;
}
// 动手验证:输入 5 3 → A(5,3) = 60(不枚举)
// 输入 2 2 → A(2,2) = 2 + 1: AB / 2: BA

✋ 你来试试

第 1 题:8 人选 3 人当班长、副班长、学习委员,有多少种选法? 三个职位不同 → 排列 A(8,3) = 8 × 7 × 6 = 336 种。
第 2 题:4 个人两两握手(不分先后:甲握乙 = 乙握甲),一共握多少次手?(提示:先按排列算 A(4,2),再想想每组被数了几遍) 按排列:A(4,2) = 4 × 3 = 12;但「甲-乙」和「乙-甲」是同一次握手,每对都被数了 2 遍 → 12 ÷ 2 = 6 次。这种「顺序没关系」的数法就是下节课的组合 C(4,2) = 6。
第 3 题:用 0~9 组一个三位数,三位数字互不相同,能组多少个? 百位:1~9 共 9 种(不能是 0);十位:0~9 去掉百位那个,9 种;个位:8 种 → 9 × 9 × 8 = 648 个。
第 4 题(加餐):10! = ?(提示:从 10! = 10 × 9! 往下推,9! = 362880 可以查表;或用程序连乘) 10! = 10 × 362880 = 3,628,800。验证:9! = 362880,8! = 40320,9 × 40320 = 362880 ✓。注意 10! 已超过 2^21,int 能存,但 13! 就必须用 long long 了。
🎯 一句话记住:排列 = 按顺序排,一个位置一个位置填、每步少一人:A(n,k) = n×(n−1)×…×(n−k+1);全排列 = n!;顺序有关系用 A,顺序没关系用 C(下节课)。