Noip2016提高组 组合数问题problem

Day2 T1

题目大意

告诉你组合数公式,其中n!=1*2*3*4*5*...*n;意思是从n个物体取出m个物体的方案数

现给定n、m、k,问在所有i(1<=i<=n),所有j(1<=j<=min(i,m))的(i,j)满足Cji是k的倍数的个数。

输入样例:
2 5  (两个数,第一个数t表示该数据有t组询问,第二个为k,接下来t行分别为n,m)
4 5  
6 7
输出样例:
0
7

数据范围:1<=n,m<=2000,1<=t<=10000,1<=k<=21

 

数论题,当时做竟然没发现这就是个杨辉三角,就是少了第一列全是1的,真是悲剧。

组合数的递推式就是Cmn=Cm-1n-1+Cmn-1

因为k一开始就固定了,所以预处理2000以内的个数,用前缀和优化优化就可以AC了,当然用二维前缀和似乎能优化到O(1),不麻烦每行一个前缀和到时候O(n)的得出答案也不会超时。

 

比完赛了也赶快转C++了23333

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 int a[2005][2005],ji[2005][2005];
 7 int n,m,ans,t,k;
 8 int main(){
 9     scanf("%d%d",&t,&k);
10     memset(a,0,sizeof(a));
11     a[1][1]=1%k;
12     if (a[1][1]==0) ji[1][1]++;
13     for (int j=2;j<=2001;j++)
14      for (int q=1;q<=min(j,2001);q++){
15          if (q==1) a[j][q]=(a[j-1][q]+1)%k;
16           else a[j][q]=(a[j-1][q]+a[j-1][q-1])%k;
17           if (a[j][q]==0) ji[j][q]=ji[j][q-1]+1; else ji[j][q]=ji[j][q-1];
18           }
19     for (int i=1;i<=t;i++){
20         scanf("%d%d",&n,&m);
21         ans=0;
22         for (int j=1;j<=n;j++)
23          ans+=ji[j][min(m,j)];
24         printf("%d\n",ans);
25     }
26     return 0;      
27     }
神奇的代码

 

posted @ 2016-12-02 16:11  ~Lanly~  阅读(2686)  评论(0编辑  收藏  举报