luogu 2822 组合数问题
第一次的想法比较简单就是裸求, 发现时间复杂度很高,
第二次先开一个数组对组合数进行维护,
然而第一次交还是WA了
细节如下
for(int i = 1; i <= MAXN; i ++) {
c[i][1] = 1;//这里是=i并且还要取模
c[i][i] = 1;
for(int j = 2; j < i; j ++) {
c[i][j] = (c[i - 1][i - 1] % k + c[i - 1][i] % k) % k;
}
}
第三次时T了, 和他们讨论才知道要前缀和优化
for(int i = 1; i <= 2000; i ++) {
for(int j = 1; j <= i; j ++) {
if(c[i][j] == 0) {
f[i][j] = f[i][j - 1] + 1;
} else {
f[i][j] = f[i][j - 1];
}
}
}
最后代码如下
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAXN 2001
using namespace std;
int t, k, n, m, ans;
long long c[MAXN][MAXN];
long long f[MAXN][MAXN]; // 前缀和优化
int read() {
int f = 1, k = 0;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') {
f = -1;
}
c = getchar();
}
while(c >= '0' && c <= '9') {
k = k * 10 + c - '0';
c = getchar();
}
return f * k;
}
int main() {
memset(c, 0, sizeof(c));
t = read(), k = read();
for(int i = 1; i <= 2000; i ++) {
c[i][1] = i % k;
c[i][i] = 1;
for(int j = 2; j < i; j ++) {
c[i][j] = (c[i - 1][j - 1]+ c[i - 1][j]) % k;
}
}
for(int i = 1; i <= 2000; i ++) {
for(int j = 1; j <= i; j ++) {
if(c[i][j] == 0) {
f[i][j] = f[i][j - 1] + 1;
} else {
f[i][j] = f[i][j - 1];
}
}
}
for(int z = 1; z <= t; z ++) {
ans = 0;
n = read(), m = read();
for(int i = 1; i <= n; i ++) {
if(i < m) {
ans += f[i][i];
} else {
ans += f[i][m];
}
}
printf("%d\n", ans);
}
return 0;
}