题解:B2164 组合数问题
题目要我们求从 \(1,2,\cdots,n\) 这 \(n\) 个数中选择 \(m\) 个数的方案数,记作 \(C_n^m\)。
首先观察边界情况。如果 \(m=0\),也就是从 \(n\) 个数中选择 \(0\) 个数,只能所有数都不选,方案数为 \(\bm{1}\)(注意不是 \(0\)),也就是说 \(C_n^0=1\)。如果 \(m=n\),也就是从 \(n\) 个数中选择 \(n\) 个数,只能所有数都选,方案数为 \(1\),也就是说 \(C_n^n=1\)。
对于 \(1\le m\le n-1\) 的情况,答案不容易直接求得,因此考虑递推。考察 \(n\) 这个数是否被选上。如果被选上,只需在 \(1,2,\cdots,n-1\) 这 \(n-1\) 个数中选择 \(m-1\) 个,方案数为 \(C_{n-1}^{m-1}\)。如果没被选,还需在 \(1,2,\cdots,n-1\) 这 \(n-1\) 个数中选择 \(m\) 个,方案数为 \(C_{n-1}^m\)。根据加法原理,我们得到 \(C_n^m=C_{n-1}^{m-1}+C_{n-1}^m\)。
\(O(n^2)\) 递推即可。
//By: OIer rui_er
#include <bits/stdc++.h>
using namespace std;
const int N = 5e3 + 5, mod = 1e9 + 7;
int n, m, C[N][N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m;
for(int i = 0; i <= n; ++i) {
C[i][0] = C[i][i] = 1;
for(int j = 1; j <= i - 1; ++j) {
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
}
}
cout << C[n][m] << endl;
return 0;
}

浙公网安备 33010602011771号