题意:给出一个棋盘为h*w,现在要从(1,1)到(h,w),其中有n个黑点不能走,问有多少种可能从左上到右下
(1 ≤ h, w ≤ 105, 1 ≤ n ≤ 2000),答案模10^9+7
思路:从(1,1)到(n,m)的方案数是c(n+m-2,n-1)
考虑不能走黑点
设dp[i]为从(1,1)走到(x[i],y[i]),中途没有走过任何一个黑点的方案数
dp[i]=dp[i]-dp[j]*c(x[i]+y[i]-x[j]-y[j],x[i]-x[j]) (x[j]<=x[i]且y[j]<=y[i])
除以阶乘取模用线性求逆元
1 const mo=1000000007; 2 var x,y:array[1..10000]of longint; 3 dp:array[1..10000]of int64; 4 exf,fac:array[0..200000]of int64; 5 n,m,k,i,j:longint; 6 7 procedure swap(var x,y:longint); 8 var t:longint; 9 begin 10 t:=x; x:=y; y:=t; 11 end; 12 13 function c(x,y:longint):int64; 14 begin 15 // if y=0 then exit(1); 16 exit(fac[x]*exf[y] mod mo*exf[x-y] mod mo); 17 end; 18 19 procedure qsort(l,r:longint); 20 var i,j,mid1,mid2:longint; 21 begin 22 i:=l; j:=r; mid1:=x[(l+r)>>1]; mid2:=y[(l+r)>>1]; 23 repeat 24 while (mid1>x[i])or(mid1=x[i])and(mid2>y[i]) do inc(i); 25 while (mid1<x[j])or(mid1=x[j])and(mid2<y[j]) do dec(j); 26 if i<=j then 27 begin 28 swap(x[i],x[j]); 29 swap(y[i],y[j]); 30 inc(i); dec(j); 31 end; 32 until i>j; 33 if l<j then qsort(l,j); 34 if i<r then qsort(i,r); 35 end; 36 37 begin 38 // assign(input,'1.in'); reset(input); 39 //assign(output,'1.out'); rewrite(output); 40 readln(n,m,k); 41 for i:=1 to k do read(x[i],y[i]); 42 inc(k); x[k]:=1; y[k]:=1; 43 inc(k); x[k]:=n; y[k]:=m; 44 qsort(1,k); 45 fac[0]:=1; 46 for i:=1 to n+m do fac[i]:=fac[i-1]*i mod mo; 47 exf[0]:=1; exf[1]:=1; 48 for i:=2 to n+m do exf[i]:=exf[mo mod i]*(mo-mo div i) mod mo; 49 for i:=1 to n+m do exf[i]:=exf[i-1]*exf[i] mod mo; 50 dp[1]:=1; 51 for i:=2 to k do 52 begin 53 dp[i]:=c(x[i]+y[i]-2,x[i]-1); 54 for j:=2 to i-1 do 55 if y[j]<=y[i] then 56 begin 57 dp[i]:=dp[i]-dp[j]*c(x[i]-x[j]+y[i]-y[j],x[i]-x[j]); 58 dp[i]:=(dp[i] mod mo+mo) mod mo; 59 end; 60 61 end; 62 writeln(dp[k]); 63 64 //close(input); 65 //close(output); 66 end.