看数据范围为 n - m 0 ~ 2000所以使用预处理的方式计算出C[i][j]
发现有两个点还是过不了,看y总的题解,才知道可以用前缀和预计算出答案
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 2010;
int C[N][N];
int t, k;
int s[N][N];
int main(){
scanf("%d%d", &t, &k);
// 首先预处理出C[n][m]
for(int i = 0; i < N; i ++){
for(int j = 0; j <= i; j ++){
if(!j) C[i][j] = 1;
else{
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % k;
}
// 如果是k的倍数则是1
if(!C[i][j]) s[i][j] = 1;
}
}
// 使用前缀和计算出C[i][j] (0 <= i <= n 0 <= j <= min(i, m))的k的倍数
for(int i = 0; i < N; i ++){
for(int j = 0; j < N; j++){
if(i) s[i][j] += s[i - 1][j];
if(j) s[i][j] += s[i][j - 1];
if(i && j) s[i][j] -= s[i - 1][j - 1];
}
}
while(t --){
int n, m;
int res = 0;
scanf("%d%d", &n, &m);
printf("%d\n", s[n][m]);
}
return 0;
}