杨辉三角表示组合数 70分
#include <bits/stdc++.h>
using namespace std;
long long a[2001][2001];
int n, m, t, k, ans;
int main()
{
scanf("%d %d", &t, &k);
for(int i=0; i<=2000; ++i){
a[i][0]=1;
a[i][i]=1;
}
//杨辉三角计算组合数
for(int i=1; i<=2000; ++i){
for(int j=1; j<=2000; ++j){
a[i][j]=a[i-1][j-1]+a[i-1][j];
}
}
while(t--){
ans=0;
scanf("%d %d", &n, &m);
for(int i=0; i<=n; ++i){
for(int j=0; j<=min(i, m); ++j){
if(a[i][j]%k==0){
ans++;
}
}
}
printf("%d\n", ans);
}
return 0;
}
边求杨辉三角边取模 90分
#include <bits/stdc++.h>
using namespace std;
long long a[2001][2001];
int n, m, t, k, ans;
int main()
{
scanf("%d %d", &t, &k);
for(int i=0; i<=2000; ++i){
a[i][0]=1;
a[i][i]=1;
}
//杨辉三角计算组合数
for(int i=1; i<=2000; ++i){
for(int j=1; j<=2000; ++j){
a[i][j]=(a[i-1][j-1]+a[i-1][j])%k;
}
}
while(t--){
ans=0;
scanf("%d %d", &n, &m);
for(int i=0; i<=n; ++i){
for(int j=0; j<=min(i, m); ++j){
if(a[i][j]%k==0){
ans++;
}
}
}
printf("%d\n", ans);
}
return 0;
}
前缀和优化查询时间 100分
#include <bits/stdc++.h>
using namespace std;
long long a[2001][2001];
int n, m, t, k, ans[2001][2001];
int main()
{
scanf("%d %d", &t, &k);
for(int i=0; i<=2000; ++i){
a[i][0]=1;
a[i][i]=1;
}
//杨辉三角计算组合数
for(int i=1; i<=2000; ++i){
for(int j=1; j<=i; ++j){
a[i][j]=(a[i-1][j-1]+a[i-1][j])%k;
}
}
for(int i=1; i<=2000; ++i){
for(int j=1; j<=i; ++j){
//前缀和, 上加左、减左上、加自己
ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1];
if(a[i][j]==0){
ans[i][j]++;
}
}
//计算ans[i+1][i+1]时, 会用到ans[i][i+1], 由于前面没计算
ans[i][i+1]=ans[i][i];
}
while(t--){
scanf("%d %d", &n, &m);
if(m>n){
printf("%d\n", ans[n][n]);
}
else{
printf("%d\n", ans[n][m]);
}
}
return 0;
}