P2822 [NOIP2016 提高组] 组合数问题 讲解
题目
先在这放两个组合数公式:
第一个公式大家都知道,第二个公式其实就是 dp。对于每个物品,要么选(
那么,运用第二个式子,提前计算出所有
那么组合数都有了,但
总体复杂度:
代码:
#include<bits/stdc++.h>
#define int long long
#define inl inline
#define reg register
#define INF 2147483647
using namespace std;
inl int read(){
int f=1,x=0;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return f*x;
}
inl void write(int x){
if(x<0){
x=-x;
putchar('-');
}
if(x>=10) write(x/10);
putchar(x%10^48);
}
#define N 2005
int t,k,f[N][N],sum[N][N],n,m;
inl void init(){
f[1][1]=1;
for(reg int i=2;i<=N-4;++i)
for(reg int j=1;j<=i;++j)
f[i][j]=(f[i-1][j]+f[i-1][j-1])%k;
for(reg int i=1;i<=N-4;++i)
for(reg int j=1;j<=N-4;++j)
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+(!f[i][j]&&j<=i);
return;
}
inl void solve(){
n=read();
m=read();
write(sum[n+1][m+1]);
puts("");
}
signed main(){
t=read();
k=read();
init();
while(t--) solve();
return 0;
}