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