51Nod 1486 大大走格子 —— 容斥
题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1486
对于每个点,求出从起点到它,不经过其他障碍点的方案数;
求一个点时,首先得到走到它的所有方案,减去 x , y 都小于它的点的方案 * 走到该点的方案数;
由于该点的方案也不包括其它障碍点,所以就是容斥。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int const maxn=1e5+5,mod=1e9+7; int h,w,n,x[maxn],y[maxn]; ll fac[maxn<<1],ans[maxn],inv[maxn];//<<1 struct N{int x,y;}p[maxn]; bool cmp(N a,N b){return a.x==b.x?a.y<b.y:a.x<b.x;} ll pw(ll a,int b) { ll ret=1; for(;b;b>>=1,a=(a*a)%mod) if(b&1)ret=(ret*a)%mod; return ret; } ll C(int n,int m) { if(m==0)return 1;//!0! return ((fac[n]*inv[m]%mod)*inv[n-m])%mod; } void init() { fac[0]=1; int mx=h+w,mxx=max(h,w); for(int i=1;i<=mx;i++)fac[i]=(fac[i-1]*i)%mod; inv[mxx]=pw(fac[mxx],mod-2); for(int i=mxx-1;i>=0;i--)inv[i]=(inv[i+1]*(i+1))%mod; } int main() { scanf("%d%d%d",&h,&w,&n); init(); for(int i=1;i<=n;i++)scanf("%d%d",&p[i].x,&p[i].y); p[++n].x=h; p[n].y=w; sort(p+1,p+n+1,cmp); for(int i=1,a,b;i<=n;i++) { a=p[i].x-1,b=p[i].y-1; ans[i]=C(a+b,b)%mod; for(int j=1;j<i;j++) { if(p[j].x>p[i].x||p[j].y>p[i].y)continue; a=p[i].x-p[j].x; b=p[i].y-p[j].y; ans[i]=(ans[i]-C(a+b,b)*ans[j]%mod+mod)%mod; } } printf("%lld\n",ans[n]%mod); return 0; }