🔺

杨辉三角:数字金字塔

每个数 = 头上两个数之和,两边永远 1——规则超简单,里面却藏着全部组合数!

💡 打个比方

想象一座数字金字塔:塔尖只有 1 个人;每往下一层多 1 个人;每个中间的人站在两个人正下方,他的数 = 头上两个人的和;每层的最左最右永远是 1。按这个规则搭出来:

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

验证规则:2 = 1+1,3 = 1+2,6 = 3+3,4 = 1+3——每个中间数都是头上两数之和,两边永远 1 ✓。这座金字塔叫杨辉三角(中国古代数学家杨辉最先画出,西方叫帕斯卡三角)。

惊喜:第 5 行的 1 4 6 4 1,正好是 C(4,0)、C(4,1)、C(4,2)、C(4,3)、C(4,4)——杨辉三角就是「组合数查表」:不用手算 C(n,k),把三角搭起来,直接读第 n+1 行第 k+1 个数就行!

术语:杨辉三角(Pascal's Triangle:每行首尾 1、中间 = 上方两数之和的数字金字塔);行与位置(三角第 n 行第 k 个数 = C(n−1,k−1),行、位置都从 1 开始数);组合数行(第 n 行从左到右正好是 C(n−1,0)、C(n−1,1)、…、C(n−1,n−1));网格路径(m×n 格子从左上到右下只向右/下的路径数 = C(m+n,m),每个格子上的数也都在三角里)。

🖼️ 大图看明白

数字金字塔:每个数 = 头上两个数之和 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 6 = 3 + 3:中间数 = 上方两数之和 第 n 行第 k 个 = C(n−1, k−1) 第 5 行 1 4 6 4 1 = C(4,0)…C(4,4) 格子路径:同一个规则(每个 = 上 + 左) 1 1 1 1 1 2 3 4 1 3 6 10 1 4 10 20 3×3 格:每个格子 = 上面 + 左边 1 6 15 20 15 6 1 三角第 7 行:中间 20 = C(6,3) = 格子角上的路径数

🧩 子任务 1:搭金字塔——前 5 行手推

🎯 小目标:记住规则「每行首尾 1,中间 = 上方两数之和」,会手推前 5 行,并会接着推第 6 行。

规则只有两句:① 每行最左最右都是 1;② 中间的数 = 它头上两个数的和。一行一行往下搭:

// 第 1 行:就一个数(首尾都是它自己)
1

// 第 2 行:首尾 1,中间没有 → 1 1
1 1

// 第 3 行:首尾 1,中间 = 1 + 1 = 2
1 2 1

// 第 4 行:首尾 1,中间 = 1+2=3、2+1=3
1 3 3 1

// 第 5 行:首尾 1,中间 = 1+3=4、3+3=6、3+1=4
1 4 6 4 1

// 规律:第 i 行有 i 个数;第 i 行第 j 个 = 第 i-1 行第 j-1 个 + 第 i-1 行第 j 个
✅ 小检查:① 第 6 行第 1 个数和第 2 个数各是多少?② 把第 6 行完整填出来。③ 为什么两边永远是 1?
看看答案 ① 第 1 个数永远是 1(首尾规则);第 2 个数 = 第 5 行第 1 个 + 第 5 行第 2 个 = 1 + 4 = 5。② 第 6 行:1 5 10 10 5 1(按第 5 行 1 4 6 4 1 逐个相加:1+4=5、4+6=10、6+4=10、4+1=5,首尾再添 1)。③ 边上的数头上只有一个数,而那个数是 1,相加结果永远是 1——规则也直接规定每行首尾 = 1。
易错:往下抄行时「照抄上一行」——中间每个数都要重新加:第 4 行是 1 3 3 1,不是把第 3 行「1 2 1」补个 1。每行 = 首尾 1 + 上方两两相加。

🧩 子任务 2:编程搭金字塔——双重循环

🎯 小目标:把规则写成递推 a[i][j] = a[i-1][j-1] + a[i-1][j],用双重循环搭出前 6 行。

用二维数组 a[行][位置](都从 1 开始数)存三角。规则翻译成代码语言:

// 递推(i = 行号,j = 行内位置)
每行首:a[i][1] = 1
每行尾:a[i][i] = 1
中间:  a[i][j] = a[i-1][j-1] + a[i-1][j]     // j 从 2 到 i-1

// 填表顺序:一行一行填(第 i 行只依赖第 i-1 行,上面填好才行)
第 1 行:a[1][1] = 1
第 2 行:a[2][1] = 1, a[2][2] = 1
第 3 行:a[3][1] = 1, a[3][3] = 1, a[3][2] = a[2][1]+a[2][2] = 2
第 4 行:a[4][1] = 1, a[4][4] = 1, a[4][2] = a[3][1]+a[3][2] = 3, a[4][3] = a[3][2]+a[3][3] = 3
第 5 行:a[5][1] = 1, a[5][5] = 1, a[5][2] = 1+3=4, a[5][3] = 3+3=6, a[5][4] = 3+1=4
第 6 行:1 5 10 10 5 1  // 按同样规则推出

// 伪代码
for i = 1 到 6:
    a[i][1] = 1
    a[i][i] = 1
    for j = 2 到 i-1:
        a[i][j] = a[i-1][j-1] + a[i-1][j]
    输出第 i 行
✅ 小检查:① 内层循环为什么从 j = 2 开始、到 j = i−1 结束?② a[6][3] = ?(写出加法)③ 为什么必须先把上一行填好?
看看答案 ① j = 1 和 j = i 是首尾,直接等于 1,不用加;只有中间 j = 2…i−1 才用递推。② a[6][3] = a[5][2] + a[5][3] = 4 + 6 = 10。③ a[i][j] 需要 a[i−1][j−1] 和 a[i−1][j] 这两个数,它们都在第 i−1 行——上一行没算出来,这一行就算不了。
易错:内层循环写成「j 从 2 到 i」——j = i 是行尾,应该直接赋 1,若去加 a[i−1][i](上一行没有第 i 个),会读到 0 或旧值,行尾就错了。

🧩 子任务 3:三角藏着全部组合数——第 n 行第 k 个 = C(n−1,k−1)

🎯 小目标:理解「第 n 行从左到右正好是 C(n−1,0)…C(n−1,n−1)」,会验证第 5 行,会直接「查表」读组合数。

把第 5 行和组合数并排放在一起:

// 第 5 行(n = 5)从左到右,就是 C(4,k),k = 0..4:
位置:   1     2     3     4     5
第5行:  1     4     6     4     1
C(4,k): C(4,0) C(4,1) C(4,2) C(4,3) C(4,4)
       = 1    = 4    = 6    = 4    = 1   // 逐个对上 ✓

// 一般规律:三角第 n 行第 k 个 = C(n−1, k−1)(行、位置都从 1 数)
C(4,2) → 第 5 行第 3 个 = 6
C(6,3) → 第 7 行第 4 个 = 20
C(7,2) → 第 8 行第 3 个 = 21

// 为什么「搭三角」和「算组合数」得到同一张表?
// 组合数也满足「上面两个加起来」的规律:C(n,k) = C(n−1,k−1) + C(n−1,k)
// (从 n 人选 k 人:分成「必选甲」和「不选甲」两类,正好相加)
// 递推一样、起点一样 → 表就一样。所以杨辉三角 = 组合数查表!
✅ 小检查:① 从三角读出 C(5,2)。② C(6,1) = ?(第 7 行第 2 个)③ C(8,4) 在三角的第几行第几个?(不用算值,说出位置)
看看答案 ① C(5,2) → 第 6 行第 3 个 = 10(第 6 行:1 5 10 10 5 1)。② 6(第 7 行:1 6 15 20 15 6 1,第 2 个)。③ C(8,4) → 第 9 行第 5 个(n−1 = 8 → 行 9;k = 4 → 位置 5)。
易错:查表差一位——C(n,k) 在第 n+1 行第 k+1 个:行、位置都从 1 开始数,n 和 k 各加 1。把 C(4,2) 查到第 4 行第 2 个(= 3)是最常见的错。

🧩 子任务 4:应用——网格路径数也是三角的数

🎯 小目标:明白「格子路径的 dp 表」和「杨辉三角」是同一个规则,会算 m×n 格子的路径数 C(m+n,m)(呼应七级 C03)。

七级 C03 做过:m 行 n 列的格子,只能向右/向下,从左上到右下的路径数。转移方程是 dp[i][j] = dp[i−1][j] + dp[i][j−1](上面 + 左边),第一行第一列 = 1。把 3×3 格子(4×4 个点)的表填出来:

// 3×3 格子的 dp 表(七级 C03 手填过,角上 = 20)
1   1   1   1
1   2   3   4
1   3   6   10
1   4   10  20

// 对照杨辉三角——这些数全都在三角里:
// 20 是三角第 7 行中间那个(第 7 行:1 6 15 20 15 6 1)
// 10、6、4、3、2……也都能在第 4~6 行找到。

// 为什么?两个递推是同一个规则:
三角:a[i][j]   = a[i-1][j-1] + a[i-1][j]   // 上方两个相加
格子:dp[i][j]  = dp[i-1][j] + dp[i][j-1]   // 上面 + 左边相加
都是「当前 = 两个相邻来源之和」,起点也都是 1 → 表里的数相同(只是排法不同:格子按「斜线」排三角的数)

// 一般结论:m 行 n 列的格子,左上→右下路径数 = C(m+n, m) = C(m+n, n)
// 理由:一共走 m 步向下 + n 步向右 = m+n 步,从中选 m 步向下 → C(m+n, m)
3×3 格子:C(6,3) = 20   // 第 7 行中间
2×3 格子:C(5,2) = 10
2×2 格子:C(4,2) = 6
✅ 小检查:① 2 行 4 列的格子(2×4),左上到右下几条路?② 为什么「格子 dp」和「三角」能产生同一批数?③ 4×4 格子(不是 3×3)的路径数 = C(8,4) = ?
看看答案 ① C(2+4, 2) = C(6,2) = 6 × 5 ÷ 2 = 15。② 两者的递推都是「当前 = 两个相邻来源之和」,边界/起点也都是 1——规则相同,结果必然相同。③ C(8,4) = (8×7×6×5) ÷ (4×3×2×1) = 1680 ÷ 24 = 70。
易错:把「m 行 n 列格子」当成「m×n 的表」——格子有 m 行 n 列格,点是 (m+1)×(n+1) 个;路径数公式用格子的行列数:C(m+n, m)。3×3 格子 → C(6,3),不是 C(3,3)。

💻 完整代码:杨辉三角生成器(搭三角 + 查 C(n,k) + 对照网格路径)

// 输入:n(2 ≤ n ≤ 7)N K(0 ≤ K ≤ N ≤ 6),一行三个数
// 输出:① 杨辉三角 n 行(金字塔形)
//       ② C(N,K) = 读三角第 N+1 行第 K+1 个
//       ③ 3×3 格子(4×4 点)路径表 + 角上路径数,对照 C(6,3)
// 示例:输入 6 4 2 → 6 行三角,C(4,2) = 6,格子角 20
#include <iostream>
using namespace std;

long long tri[16][16];   // tri[i][j]:三角第 i 行第 j 个(都从 1 开始)

int main() {
    int n, N, K;
    cin >> n >> N >> K;

    // 1. 搭三角:首尾 1,中间 = 上方两数之和
    for (int i = 1; i <= n; i++) {
        tri[i][1] = 1;
        tri[i][i] = 1;
        for (int j = 2; j < i; j++)
            tri[i][j] = tri[i-1][j-1] + tri[i-1][j];
    }

    // 2. 输出 n 行(金字塔形:前面补空格)
    for (int i = 1; i <= n; i++) {
        for (int t = 0; t < n - i; t++)
            cout << "   ";
        for (int j = 1; j <= i; j++)
            cout << tri[i][j] << "  ";
        cout << endl;
    }

    // 3. 查表:C(N,K) 在第 N+1 行第 K+1 个
    cout << "C(" << N << "," << K << ") = " << tri[N+1][K+1] << endl;

    // 4. 3×3 格子(4×4 点)路径表:每个 = 上 + 左,首行首列 = 1
    long long f[5][5] = {};
    for (int i = 1; i <= 4; i++) f[i][1] = 1;
    for (int j = 1; j <= 4; j++) f[1][j] = 1;
    for (int i = 2; i <= 4; i++)
        for (int j = 2; j <= 4; j++)
            f[i][j] = f[i-1][j] + f[i][j-1];
    for (int i = 1; i <= 4; i++) {
        for (int j = 1; j <= 4; j++)
            cout << f[i][j] << " ";
        cout << endl;
    }
    // 注意:n 要 ≥ 7,三角第 7 行才搭好了
    cout << "格子角 = " << f[4][4] << " = C(6,3) = "
         << tri[7][4] << endl;
    return 0;
}
// 动手验证:输入 7 6 3 → 7 行三角,C(6,3) = 20,格子角 20(两边一致)
// 输入 6 5 2 → C(5,2) = 10

✋ 你来试试

第 1 题:写出杨辉三角第 6 行和第 7 行。 第 6 行:1 5 10 10 5 1;第 7 行:1 6 15 20 15 6 1(每行 = 上一行两两相加,首尾添 1)。
第 2 题:从三角读出 C(6,2) 和 C(6,4)。 第 7 行是 1 6 15 20 15 6 1:C(6,2) = 第 7 行第 3 个 = 15;C(6,4) = 第 7 行第 5 个 = 15。两个一样——三角左右对称。
第 3 题:2 行 4 列的格子,从左上到右下(只向右/下)有几条路径? 走 2 步向下 + 4 步向右,共 6 步,选 2 步向下:C(6,2) = 6 × 5 ÷ 2 = 15 条。也可以填 3×5 的 dp 表验证,角上正好是 15。
第 4 题(加餐):第 8 行是 1 7 21 35 35 21 7 1——为什么左右对称?所有行都对称吗? 对称因为「选 k 个」和「不选的 n−k 个」一一对应:C(n,k) = C(n,n−k)。第 8 行左右完全镜像;杨辉三角的每一行都对称。中间也是最大:奇数个数的行中间只有一个数(如第 7 行的 20),偶数个数的行中间两个数相等且最大(如第 6 行的 10 10)。
🎯 一句话记住:杨辉三角 = 数字金字塔,每行首尾 1、中间 = 上方两数之和;第 n 行第 k 个 = C(n−1,k−1)——三角就是组合数查表;格子路径同一个规则,m 行 n 列格子路径数 = C(m+n,m)。