【洛谷 2822】组合数问题 组合数、杨辉三角、前缀和。
——90%—
杨辉三角递推
#include <cstdio>
#include <algorithm>
const int MAXN = 2007;
int n, m, t, k, f[MAXN][MAXN], sum[MAXN][MAXN];
void fs() {
for (int i = 0; i < MAXN; i++) f[i][0] = 1; // 注意初始化
for (int i = 1; i < MAXN; i++)
for (int j = 1; j < MAXN; j++)
f[i][j] = (f[i - 1][j] + f[i - 1][j - 1]) % k;
}
int main() {
scanf("%d%d", &t, &k);
fs();
//
// for(int i = 0; i < 10; i++) {
// for (int j = 0; j < 10; j++) printf("%d ", f[i][j]);
// printf("\n");
// }
while (t--) {
int ans = 0;
scanf("%d%d", &n, &m);
for (int i = 0; i <= n; i++)
for (int j = 0; j <= std::min(i, m); j++)
if (f[i][j] == 0) ans++;
printf("%d\n", ans);
}
return 0;
}
—100%—
二维前缀和优化。
#include <cstdio>
const int MAXN = 2000 + 7;
int T, k, n, m, c[MAXN][MAXN], s[MAXN][MAXN];
void get() {
for (int i = 0; i <= 2000; i++)
for (int j = 0; j <= i; j++) {
if (!j && !i) c[i][j] = 1 % k;
else c[i][j] = (c[i - 1][j] +c[i - 1][j - 1]) % k;
}
}
void gets() {
if (!c[0][0]) s[0][0] = 1;
for (int i = 0; i <= 2000; i++) {
for (int j = 0; j <= i; j++) {
if (!i && !j) continue;
else {
if ((!i && j) || i == j) { // 特殊处理处理边界情况
s[i][j] = s[i][j - 1];
if (!c[i][j]) s[i][j]++;
} else if (i && !j) {
s[i][j] = s[i - 1][j];
if (!c[i][j]) s[i][j]++;
} else {
s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1];
if (!c[i][j]) s[i][j]++;
}
}
}
}
}
int main() {
scanf("%d%d", &T, &k);
get();
gets();
while (T--) {
scanf("%d%d", &n, &m);
printf("%d\n", s[n][m > n ? n : m]);
}
return 0;
}

浙公网安备 33010602011771号