P2822 组合数问题——巧用前缀和

P2822 组合数问题

求的是C(i,j)有多少个是k的倍数;

首先,求组合数是有技巧的,

 

 

用杨辉三角求组合数,爽的一批;

但是,这样只能得90分,两个点T了;

因为k是不变的,我们可以用前缀和的思想求出每个点的答案;

注意ans[i][i+1]=ans[i][i];因为下一个点是比上一个点多一个的;

为了不超过整数范围,我们可以%k;

 

 

 

 

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2010;
int c[maxn][maxn];
int n,k;
int ans[maxn][maxn];
void build()
{
    c[0][0]=1;
    c[1][0]=c[1][1]=1;
    for(int i=2;i<=2000;i++)
    {
        c[i][0]=1;
        for(int j=1;j<=i;j++)
        {
            c[i][j]=c[i-1][j]%k+c[i-1][j-1]%k;
            ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1];
            if(c[i][j]%k==0) ans[i][j]++;
        }
        ans[i][i+1]=ans[i][i];
    }
}
int T,m;
int x;
int main()
{
    
    scanf("%d%d",&T,&k);
    build();
    while(T--)
    {
        scanf("%d%d",&n,&m);
        x=min(n,m);
        printf("%d\n",ans[n][x]);
    }
    return 0;
}

 

 

posted @ 2019-10-07 09:35  AiRomance  阅读(200)  评论(0编辑  收藏  举报