把网格路线拆成步序列:每条路恰含 m-1 步上、n-1 步右,路线与「在总步数里选上步位置」一一对应,答案即组合数 C(m+n-2, m-1),用 math.comb 一步求出。
OJ: roj
题目 ID: 1194
难度:入门
标签:入门网格动态规划组合计数python
创建: 2026-09-29 22:50
更新: 2026-10-05 05:11
题目描述
X 桌子上有
思路
每条路线必然恰含
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-29 22:50
# update_at: 2026-10-04 14:22
import sys
from math import comb
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
m, n = next(data), next(data)
# 任一条路线都恰含 m-1 步"上"与 n-1 步"右",路线只由这 m+n-2 步的顺序决定:
# 在总步数里任选 m-1 个位置放"上",其余放"右",故答案为组合数。
print(comb(m + n - 2, m - 1))
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-05 05:11
* update_at: 2026-10-05 05:11
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// 题目数据:m, n 都是 int 范围内的正整数,且 m+n <= 20;用 ll 只是保险。
int m, n;
// 逐步累乘计算 C(N, k) = N*(N-1)*...*(N-k+1) / k*(k-1)*...*1。
// 顺序乘法再除以同阶分母,避免中间出现非整数。
ll comb(int N, int k) {
if (k < 0 || k > N) return 0;
if (k > N - k) k = N - k; // 利用 C(N,k) = C(N,N-k) 减少乘法次数
ll num = 1;
ll den = 1;
for (int i = 0; i < k; i++) {
num *= (N - i);
den *= (i + 1);
}
return num / den;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> m >> n;
// 每条路线恰含 m-1 步上、n-1 步右;路线数等价于从 m+n-2 步里选 m-1 步作为上步,
// 答案 = C(m+n-2, m-1)。
cout << comb(m + n - 2, m - 1) << endl;
return 0;
}