题目信息
解题思路
- 组合数其实可以看成杨辉三角,Cij就是第i行第j列。
- 状态转移方程:Cij = (Ci-1j + Cij-1) % k
- 优化:前缀和(预处理O(n2),查询O(1))
不太熟悉前缀和的童鞋请移步there
代码实现
#include <bits/stdc++.h>
using namespace std;
const int N = 2e3 + 5;
int t, k, n, m;
int c[N][N], s[N][N];
int main() {
ios :: sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> t >> k;
n = 2e3;
for (int i = 0; i <= n; ++i) {
c[i][0] = 1;
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % k;
if (i == j) {
s[i][j] = s[i][j - 1] + (c[i][j] == 0);
} else {
s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + (c[i][j] == 0);
}
}
}
while (t--) {
cin >> n >> m;
m = min(n, m);
cout << s[n][m] << '\n';
}
return 0;
}