传送门
令f[i]f[i]f[i]表示对于第iii个棋子,从(1,1)(1,1)(1,1)出发到它不经过其它棋子的方案数。
于是我们假设(h,w)(h,w)(h,w)有一个棋子,求出它的fff值就可以了。
然后考虑容斥转移fff数组。
根据定义,我们求出从(1,1)(1,1)(1,1)出发到它的总方案数,再减去经过了其它棋子的方案数。
然后再考虑如何才会补充不漏。
发现从之前每一个fff转移过来就行了。
fi=(xi+yi−2xi−1)−∑fj∗(xi−yi+xj−yjxi−xj)f_i=\binom{x_i+y_i-2}{x_i-1}-\sum f_j*\binom{x_i-y_i+x_j-y_j}{x_i-x_j}fi=(xi−1xi+yi−2)−∑fj∗(xi−xjxi−yi+xj−yj)
代码:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
typedef long long ll;
const int N=2e3+5,M=1e5+5,mod=1e9+7;
int h,w,n,f[N],fac[M+M],ifac[M+M];
struct Node{
int x,y;
friend inline bool operator<(const Node&a,const Node&b){return a.x==b.x?a.y<b.y:a.x<b.x;}
}p[N];
inline int C(const int&n,const int&m){return (ll)fac[n]*ifac[m]%mod*ifac[n-m]%mod;}
int main(){
h=read(),w=read(),n=read(),fac[0]=fac[1]=ifac[0]=ifac[1]=1;
for(int i=2;i<=h+w;++i)fac[i]=(ll)fac[i-1]*i%mod;
for(int i=2;i<=h+w;++i)ifac[i]=(ll)ifac[mod%i]*(mod-mod/i)%mod;
for(int i=2;i<=h+w;++i)ifac[i]=(ll)ifac[i]*ifac[i-1]%mod;
for(int i=1;i<=n;++i)p[i].x=read(),p[i].y=read();
p[++n]=(Node){h,w},sort(p+1,p+n+1);
for(int i=1;i<=n;++i){
f[i]=C(p[i].x+p[i].y-2,p[i].x-1);
for(int j=1;j<i;++j){
if(p[j].y>p[i].y)continue;
f[i]=f[i]-(ll)f[j]*C(p[i].x+p[i].y-p[j].x-p[j].y,p[i].x-p[j].x)%mod;
if(f[i]<0)f[i]+=mod;
}
}
cout<<f[n];
return 0;
}