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 }