先把黑块按坐标排序。
dp[i]表示到第i个黑块且之前没有经过黑块的方案数,那么每一个dp[i]中的方案都是完全不相同的。递推的方法是dp[i]=C(xi+yi,xi)-sum(dp[j]*C(xi-xj+yi-yj,xi-xj)) (j<i)
dp[j]*C(xi-xj+yi-yj,xi-xj)就是从1,1经过第j个黑块到i的路径数,用总路径数减去所有的这些不合法的路径数就是dp[i],(剪去的路径中没有重复的)。
由于组合数太大,需要用乘法逆元预处理出每个阶乘的逆元。模板在下面。
pair的默认排序规则就是先按key再按value从小到大。
注意预处理阶乘要到2*100000
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#include <map>
#include <algorithm>
#define LL long long
const int mod=1e9+7;
#include <vector>
LL fact[200200];
LL ifact[200200];
int h,w,n;
LL dp[2005];
pair<int,int> G[2005];
LL ex(LL a,LL e)
{
if(e==0) return 1;
LL res=ex(a,e/2);
res*=res;
res%=mod;
if(e%2==1) res*=a;
res%=mod;
return res;
}
LL inv(LL a)
{
return ex(a,mod-2);
}
LL C(int h,int w)
{
if(h<0||w<0) return 0;
LL res=fact[h+w];
res*=ifact[h];
res%=mod;
res*=ifact[w];
res%=mod;
return res;
}
void init(){
fact[0]=1;
ifact[0]=1;
for(int i=1; i<200005; i++)
{
fact[i]=fact[i-1]*i;
fact[i]%=mod;
ifact[i]=inv(fact[i]);
}
}
int main(){
scanf("%d%d%d",&h,&w,&n);
init();
for(int i=0;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
G[i]=make_pair(x,y);
}
sort(G,G+n);
G[n]=make_pair(h,w);
for(int i=0;i<=n;i++){
int x=G[i].first-1,y=G[i].second-1;
dp[i]=C(x,y);
for(int j=0;j<i;j++){
int xx=G[i].first-G[j].first;
int yy=G[i].second-G[j].second;
LL tmp=C(xx,yy)*dp[j];
tmp%=mod;
dp[i]-=tmp;
while(dp[i]<0) dp[i]+=mod;
}
}
printf("%lld\n",dp[n]);
}
dp[i]表示到第i个黑块且之前没有经过黑块的方案数,那么每一个dp[i]中的方案都是完全不相同的。递推的方法是dp[i]=C(xi+yi,xi)-sum(dp[j]*C(xi-xj+yi-yj,xi-xj)) (j<i)
dp[j]*C(xi-xj+yi-yj,xi-xj)就是从1,1经过第j个黑块到i的路径数,用总路径数减去所有的这些不合法的路径数就是dp[i],(剪去的路径中没有重复的)。
由于组合数太大,需要用乘法逆元预处理出每个阶乘的逆元。模板在下面。
pair的默认排序规则就是先按key再按value从小到大。
注意预处理阶乘要到2*100000
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#include <map>
#include <algorithm>
#define LL long long
const int mod=1e9+7;
#include <vector>
LL fact[200200];
LL ifact[200200];
int h,w,n;
LL dp[2005];
pair<int,int> G[2005];
LL ex(LL a,LL e)
{
if(e==0) return 1;
LL res=ex(a,e/2);
res*=res;
res%=mod;
if(e%2==1) res*=a;
res%=mod;
return res;
}
LL inv(LL a)
{
return ex(a,mod-2);
}
LL C(int h,int w)
{
if(h<0||w<0) return 0;
LL res=fact[h+w];
res*=ifact[h];
res%=mod;
res*=ifact[w];
res%=mod;
return res;
}
void init(){
fact[0]=1;
ifact[0]=1;
for(int i=1; i<200005; i++)
{
fact[i]=fact[i-1]*i;
fact[i]%=mod;
ifact[i]=inv(fact[i]);
}
}
int main(){
scanf("%d%d%d",&h,&w,&n);
init();
for(int i=0;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
G[i]=make_pair(x,y);
}
sort(G,G+n);
G[n]=make_pair(h,w);
for(int i=0;i<=n;i++){
int x=G[i].first-1,y=G[i].second-1;
dp[i]=C(x,y);
for(int j=0;j<i;j++){
int xx=G[i].first-G[j].first;
int yy=G[i].second-G[j].second;
LL tmp=C(xx,yy)*dp[j];
tmp%=mod;
dp[i]-=tmp;
while(dp[i]<0) dp[i]+=mod;
}
}
printf("%lld\n",dp[n]);
}