Noip2016提高组 组合数问题problem

时间:2023-03-08 16:46:29
Noip2016提高组 组合数问题problem

Day2 T1

题目大意

告诉你组合数公式Noip2016提高组 组合数问题problem,其中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

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int a[][],ji[][];
int n,m,ans,t,k;
int main(){
scanf("%d%d",&t,&k);
memset(a,,sizeof(a));
a[][]=%k;
if (a[][]==) ji[][]++;
for (int j=;j<=;j++)
for (int q=;q<=min(j,);q++){
if (q==) a[j][q]=(a[j-][q]+)%k;
else a[j][q]=(a[j-][q]+a[j-][q-])%k;
if (a[j][q]==) ji[j][q]=ji[j][q-]+; else ji[j][q]=ji[j][q-];
}
for (int i=;i<=t;i++){
scanf("%d%d",&n,&m);
ans=;
for (int j=;j<=n;j++)
ans+=ji[j][min(m,j)];
printf("%d\n",ans);
}
return ;
}

神奇的代码