P2822 [NOIP2016 提高组] 组合数问题

P2822 [NOIP2016 提高组] 组合数问题

0x01 题意

给定\(n,m\)\(k\),对于所有的\(0\le i\le n,0\le j\le min(i,m)\)有多少对\((i,j)\)满足\(k|\tbinom{i}{j}\)

\(1\)\(k\),多组\(n\),\(m\)

0x02 解

预处理出来杨辉三角,因为第\(i\)行第\(j\)列就是\(\tbinom{i}{j}\)的值

\(k\)只有一个,所以可以把所有杨辉三角里的数\(\%k\)\(0\)的个数就星了

但是会超时

用二维前缀和

注意算每行最后一个答案的时候,它上面的数就是,它左上方的数,因为\(\tbinom{n}{m}=0\,(n<m)\)

0x03 码

#include<bits/stdc++.h>
using namespace std;
const int N=2010;

int n,m,k,t;

int san[N][N],f[N][N];

int main(){
	cin>>t>>k;
	
	san[0][0]=san[1][0]=san[1][1]=1;
	for(int i=2;i<=2000;i++){
		san[i][0]=1;
		for(int j=1;j<=i;j++){
			san[i][j]=(san[i-1][j-1]%k+san[i-1][j]%k)%k;
			f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
			if(san[i][j]==0) f[i][j]++;
		}
		f[i][i+1]=f[i][i];
	}
	
	while(t--){
		cin>>n>>m;
		if(m>n) cout<<f[n][n]<<endl;
		else cout<<f[n][m]<<endl;
		
	}
	
	
	
	return 0;
}
posted @ 2021-03-08 09:24  wsy_jim  阅读(107)  评论(0编辑  收藏  举报