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;
}

浙公网安备 33010602011771号