可以用总方案数减去经过障碍物的方案数。
先写一个判断某点是否可达的函数~ check(a,b)
再写一个某点到某点的方案数的函数~ cal(x1,x2,y1,y2)
设随便走 从(1,1)到(n,m)的方案数为P
设从(1,1)走到第i个障碍物并且不经过其余障碍物的方案数为num[i]。
那么 answer = P - sum{ num[i] * cal(x[i],y[i],n,m) }。
计算num[i] 可以将所有的障碍物按照x从小到大排个序,然后o(r*r)效率得到。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-8; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } inline int read() { char c = getchar(); while(!isdigit(c)) c = getchar(); int x = 0; while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar(); } return x; } LL mod=110119; LL PowMod(LL a,LL b,LL MOD){ LL ret=1; while(b){ if(b&1) ret=(ret*a)%MOD; a=(a*a)%MOD; b>>=1; } return ret; } LL fac[120000]; LL Lucas(LL n,LL m,LL p) { LL ret=1; while(n&&m) { LL a=n%p,b=m%p; if(a<b) return 0; ret=(ret*fac[a]*PowMod(fac[b]*fac[a-b]%p,p-2,p))%p; n/=p, m/=p; } return ret; } bool check(LL a,LL b) { if((a+b+1)%3!=0) return 0; LL f=(a+b+1)/3; f--; LL aa=a-f,bb=b-f; if(aa<=0||bb<=0) return 0; return 1; } LL cal(LL A,LL B,LL a,LL b) { if(!check(a,b)) return 0; if(!check(A,B)) return 0; LL f,na,nb,nA,nB; f=(A+B+1)/3; f--; nA=A-f,nB=B-f; f=(a+b+1)/3; f--; na=a-f,nb=b-f; if(na-nA<0||nb-nB<0) return 0; return Lucas(nb-nB+na-nA,na-nA,mod); } LL N,M,r,num[110]; struct X { LL x,y; }s[110]; bool cmp(X a,X b){return a.x<b.x;} int main() { int cas=1; fac[0]=1; for(int i=1;i<=(int)mod;i++) fac[i]=(fac[i-1]*i)%mod; while(~scanf("%lld%lld%d",&N,&M,&r)) { for(int i=1;i<=r;i++) scanf("%lld%lld",&s[i].x,&s[i].y); sort(s+1,s+1+r,cmp); printf("Case #%d: ",cas++); if(!check(N,M)) printf("0\n"); else { LL ans=cal(1,1,N,M); for(int i=1;i<=r;i++) { num[i]=cal(1,1,s[i].x,s[i].y); for(int j=1;j<i;j++) num[i]=(num[i]-num[j]*cal(s[j].x,s[j].y,s[i].x,s[i].y)%mod+mod)%mod; } for(int i=1;i<=r;i++) ans=(ans-num[i]*cal(s[i].x,s[i].y,N,M)%mod+mod)%mod; printf("%lld\n",ans); } } return 0; }
时间: 2024-10-11 22:30:22