vijos 2006
排列组合。
递推式C(n,m)=C(n-1,m)+C(n-1,m-1)。
容斥+前缀和记录一下即可,询问O(1)。
#include<cstdio> #include<cctype> #include<algorithm> using namespace std; int read(){ char c; while(!isdigit(c=getchar())); int x=c-'0'; while(isdigit(c=getchar())) x=x*10+c-'0'; return x; } int c[2001][2001],sum[2001][2001]; int main(){ int t=read(),k=read(); for(int i=0;i<=2000;i+=1) for(int j=0;j<=i;j+=1){ if(i==j || !j) c[i][j]=1; else c[i][j]=(c[i-1][j]+c[i-1][j-1])%k; } for(int i=0;i<=2000;i+=1) for(int j=0;j<=2000;j+=1){ if(i>=j) sum[i][j]=!c[i][j]; if(j<=i && j>=1) sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]; if(j>i) sum[i][j]+=sum[i][j-1]; } while(t--){ int n=read(),m=read(); printf("%d\n",sum[n][m]); } return 0; }