C++完整参考代码
#include <iostream>
using namespace std;
int main() {
int n = 6, m = 3; // 求 C(6, 3)
// 方法一:组合数公式 C(n,m) = [n(n-1)…(n-m+1)] / m!
// 边乘边除,每一步结果都是整数,可避免中间溢出
long long c = 1;
for (int i = 1; i <= m; i++)
c = c * (n - m + i) / i; // 依次乘 4、5、6,依次除 1、2、3
cout << "C(6,3) = " << c << endl; // 20
// 方法二:杨辉三角递推 C(n,m) = C(n-1,m-1) + C(n-1,m)
long long tri[10][10] = {0};
for (int i = 0; i <= n; i++) {
tri[i][0] = 1; // 每行第一个都是 1
for (int j = 1; j <= i; j++)
tri[i][j] = tri[i - 1][j - 1] + tri[i - 1][j];
}
cout << "杨辉三角 C(6,3) = " << tri[n][m] << endl; // 20
return 0;
}
答案:C(6, 3) = 20。所以 3×3 网格从左下走到右上共有 20 条最短路径。
思路:从左下走到右上,一共要走 3 步向右 + 3 步向上 = 6 步。只要决定"这 6 步里哪 3 步是向右",整条路线就唯一确定了,所以有 C(6,3) 种走法:C(6,3) = 6×5×4 ÷ (3×2×1) = 120 ÷ 6 = 20。程序里给了两种实现:公式法(边乘边除)和杨辉三角递推法(C(n,m)=C(n-1,m-1)+C(n-1,m),本质就是程序里的网格 DP f[i][j] = f[i-1][j] + f[i][j-1])。
考点:组合数 C(n,m) 的意义与公式、杨辉三角递推、"网格路径 = 组合计数"这个经典模型。
易错:① 数步数别弄错:3×3 网格要走 3 步右 + 3 步上共 6 步,所以是 C(6,3),不是 C(3,3);② 公式里分子是 6×5×4、分母是 3×2×1,别只除一半;③ 数据范围要留意:组合数增长极快——C(20,10) = 184756、C(30,15) = 155117520 都还装得下 int,但 C(34,17) = 2333606220 就已经超过 int 上限 2147483647,C(67,33) = 14226520737620288370 更是连 64 位整数都装不下,这时要用 long long、高精度,或者直接在模意义下用杨辉三角 / 逆元来算。