题解 008 题目 P2822

· · 题解

题目分析

通过代码

#include<iostream>
using namespace std;
int t,k,n,m,c[2005][2005],x[2005][2005],a[2005][2005];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>t>>k;
    for (int i=0;i<=2000;i++){
        for (int j=0;j<=i;j++){
            if (j==0||j==i) c[i][j]=1;
            else c[i][j]=(c[i-1][j-1]%k+c[i-1][j]%k)%k; // 记得取模。
            if (c[i][j]==0) x[i][j]+=1; // 如果 c[i][j] 整除 k,将 x[i][j] 记为 1,查询时输出它的前缀和。
        }
    } // 预处理,注意边界情况。
    for (int i=0;i<=2000;i++){
        for (int j=0;j<=2000;j++){
            if (i>0&&j>0) a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+x[i][j];
            else if (i>0&&j==0) a[i][j]=a[i-1][j]+x[i][j];
            else if (i==0&&j>0) a[i][j]=a[i][j-1]+x[i][j];
            else a[i][j]=x[i][j];
        }
    } // 计算 x 数组的前缀和,同样记得注意边界情况。
    while (t--){
        cin>>n>>m;
        cout<<a[n][m]<<"\n";
    } // 每次访问,输出前缀和。
    return 0;
}