题目链接:P2822 组合数问题
很水的一道二维前缀和,我们只需要**组合数递推(杨辉三角)**就好了,就是这个:
$$C_n^m=C_{n-1}^m+C_{n-1}^{m-1}$$
就好了,边递推边取膜,二维前缀和维护次数即可。
(我不会告诉你我的循环边界写错$WA$了$n$次
$Code$:
#include<iostream> #include<cstdio> #include<cmath> using namespace std; long long f[2005][2005],sum[2005][2005]; long long ch[2005][2005],cs[2005][2005]; int t,n,m,k; int main() { //freopen("data.in","r",stdin); //freopen("baoli.out","w",stdout); scanf("%d%d",&t,&k); for(int i=0;i<=2001;i++) { f[i][0]=1; ch[i][0]=0; ch[0][i]=0; cs[0][i]=0; cs[0][i]=0; sum[i][0]=0; sum[0][i]=0; } for(int i=1;i<=2001;i++) { for(int j=1;j<=i;j++) { f[i][j]=(f[i-1][j]+f[i-1][j-1])%k; } } for(int i=1;i<=2001;i++) { for(int j=1;j<=i;j++) { if(f[i][j]==0) f[i][j]=1; else f[i][j]=0; } } for(int i=1;i<=2001;i++) { for(int j=1;j<=i;j++) { ch[i][j]=ch[i][j-1]+f[i][j]; } } for(int i=1;i<=2001;i++) { for(int j=i;j<=2001;j++) { cs[j][i]=cs[j-1][i]+f[j][i]; } } for(int i=1;i<=2001;i++) { for(int j=1;j<=i;j++) { sum[i][j]=sum[i-1][j-1]+cs[i][j]+ch[i][j]-f[i][j]; } } while(t--) { scanf("%d%d",&n,&m); if(n==0||m==0) cout<<0<<endl; else printf("%lld\n",sum[n][min(n,m)]); } return 0; } /*1 12 1962 1183*/