[NOIp2016提高组]组合数问题

题目大意:
  给定n,m和k,对于所有的0<=i<=n,0<=j<=min(i,m)有多少对(i,j)满足C(j,i)是k的倍数。

思路:
  先预处理出组合数,再预处理一下能整除个数的前缀和,最后直接答即可。

 1 #include<cstdio>
 2 #include<cctype>
 3 inline int getint() {
 4     register char ch;
 5     while(!isdigit(ch=getchar()));
 6     register int x=ch^'0';
 7     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 8     return x;
 9 }
10 const int N=2001;
11 int c[N][N],s[N][N];
12 int main() {
13     int T=getint(),k=getint();
14     for(register int i=0;i<N;i++) {
15         c[i][0]=1;
16         for(register int j=1;j<=i;j++) {
17             c[i][j]=(c[i-1][j-1]+c[i-1][j])%k;
18         }
19     }
20     for(register int i=1;i<N;i++) {
21         for(register int j=1;j<N;j++) {
22             s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1];
23             if(!c[i][j]&&j<=i) s[i][j]++;
24         }
25     }
26     while(T--) {
27         const int n=getint(),m=getint();
28         printf("%d\n",s[n][m]);
29     }
30     return 0;
31 }

 

posted @ 2017-11-03 17:03  skylee03  阅读(155)  评论(0编辑  收藏  举报