【洛谷 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; }