题目链接:https://www.luogu.com.cn/problem/P2822
运用杨辉三角递推预处理出组合数。用二维前缀和记录有多少对满足k|(i,j)。
在预处理组合数时,因为最终都要除以k,所以可以在递推求的时候%k。注意二维前缀和求的时候的边界情况:
sum[i][i+1]=sum[i][i]。
再注意输入中m可能大于n。
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int N=2005; 5 int T,k; 6 int c[N][N],sum[N][N]; 7 void init(){ 8 c[1][1]=1; 9 for(int i=0;i<=2000;i++) c[i][0]=1; 10 for(int i=2;i<=2000;i++) 11 for(int j=1;j<=i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%k; 12 for(int i=2;i<=2000;i++){ 13 for(int j=1;j<=i;j++){ 14 sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]; 15 if(c[i][j]==0) sum[i][j]++; 16 } 17 sum[i][i+1]=sum[i][i]; 18 } 19 } 20 int main(){ 21 scanf("%d%d",&T,&k); 22 init(); 23 while(T--){ 24 int n,m; 25 scanf("%d%d",&n,&m); 26 if(m>n) m=n; 27 printf("%d ",sum[n][m]); 28 } 29 return 0; 30 }