题目链接:51nod 1486
sol:
考虑没有障碍的情况,从(1,1)到(n,m)答案可直接算出为。考虑经过不合法点(x,y)到达(n,m)的路径,答案为
。按照x为第一关键字,y为第二关键字对不合法点进行排序,设dp[i]为不经过其余不合法点从起点走到第i个点的方案数,则只有左上方的点对其方案有影响,依次删掉即可。可自行添加最后一个点处理答案。
可得到递推式。
code:
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <sstream>
using namespace std;
typedef long long ll;
const int maxn = 3e3 + 50;
const ll mod = 1e9 + 7;
ll fac[maxn];
ll inv[maxn];
inline ll qpow(ll a, ll b){
ll sum = 1;
while (b) {
if (b & 1) sum = sum * a % mod;
a = a * a % mod;
b >>= 1;
}
return sum;
}
inline ll Lnv(int n){
return qpow(n, mod - 2);
}
void init(int n){
fac[0] = fac[1] = inv[0] = inv[1] = 1;
for (int i = 2; i <= n; i++) {
fac[i] = fac[i - 1] * i % mod;
}
inv[n] = Lnv(fac[n]);
for (int i = n - 1; i > 1; i--) {
inv[i] = inv[i + 1] * (i + 1) % mod;
}
}
inline ll C(int n, int m){
return fac[n] * inv[n - m] % mod * inv[m] % mod;
}
struct node{
int x,y;
bool operator <(const node& s) const{
return x==s.x?y<s.y:x<s.x;
}
}q[maxn];
ll cal(int x,int y){
return C(x+y,x);
}
ll dp[maxn];
int main(){
int h,w,n;
scanf("%d%d%d",&h,&w,&n);
init(maxn-1);
for(int i=1;i<=w;i++){
scanf("%d%d",&q[i].x,&q[i].y);
}
++n;
q[n].x = h;
q[n].y = w;
sort(q+1,q+n+1);
for(int i=1;i<=n;i++){
// cout<<i<<' '<<q[i].x<<' '<<q[i].y<<endl;
dp[i] = cal(q[i].x-1,q[i].y-1);
for(int j=1;j<i;j++){
if(q[j].y>q[i].y) continue;
ll ret = cal(q[i].x-q[j].x,q[i].y-q[j].y);
(ret*=dp[j])%=mod;
// cout<<"ret "<<ret<<endl;
(dp[i]+=mod-ret)%=mod;
}
// cout<<dp[i]<<endl;
}
printf("%lld\n",dp[n]);
return 0;
}