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

本题考察了组合数的递推以及矩阵前缀和。我们可以得出:

\[C_n^m=\frac{n!}{m!\cdot(n-m)!}=\frac{(n-1)!}{(n-m-1)!\cdot m!}+\frac{(n-1)!}{(n-m)!\cdot (m-1)!}=\left\{ \begin{aligned} &1,&&m=n\quad or \quad m=0\\ &C_{n-1}^m+C_{n-1}^{m-1},&&otherwise \end{aligned} \right. \]

这其实也是一个杨辉三角

如何解决数据范围极大的问题?使用矩阵前缀和即可。见代码:

#include<bits/stdc++.h>
using namespace std;
int s[2005][2005],c[2005][2005],t,k,n,m;
signed main(){
	scanf("%d%d",&t,&k);
	c[1][1]=1;
	for(int i=0;i<=2000;c[i][0]=1,i++)
		for(int j=1;j<=i;j++)
			c[i][j]=(c[i-1][j]+c[i-1][j-1])%k;
	for(int i=2;i<=2000;s[i][i+1]=s[i][i],i++)
		for(int j=1;j<=i;j++)
			s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+!(c[i][j]);
	while(t--){
		scanf("%d%d",&n,&m);
		if(m>n) m=n;
		if(m==0) puts("1");
		printf("%d\n",s[n][m]);
	}
	return 0;
}
posted @ 2022-12-04 10:17  robinyqc  阅读(40)  评论(0)    收藏  举报