vijos 2006

排列组合。

递推式C(n,m)=C(n-1,m)+C(n-1,m-1)。

容斥+前缀和记录一下即可,询问O(1)。

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
int read(){
    char c; while(!isdigit(c=getchar())); int x=c-'0';
    while(isdigit(c=getchar())) x=x*10+c-'0'; return x;
}
int c[2001][2001],sum[2001][2001];
int main(){
    int t=read(),k=read();
    for(int i=0;i<=2000;i+=1)
        for(int j=0;j<=i;j+=1){
            if(i==j || !j) c[i][j]=1;
            else c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;
        }
    for(int i=0;i<=2000;i+=1)
        for(int j=0;j<=2000;j+=1){
            if(i>=j) sum[i][j]=!c[i][j];
            if(j<=i && j>=1) sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
            if(j>i) sum[i][j]+=sum[i][j-1];
        }
    while(t--){
        int n=read(),m=read();
        printf("%d\n",sum[n][m]);
    }
    return 0;
}

 

posted @ 2017-10-27 11:25  或是七一  阅读(81)  评论(0编辑  收藏  举报