从(u,v)到(n,m)相当于走x步1*2和y步2*1满足 x+2y=n-u,2x+y=m-v

解方程然后组合计数即可。

以前没写过lucas定理,写一下……

其实就是C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p

顺便这题的容斥有特殊性,只要把点排序,然后用f[i]表示到第i个障碍且路上没有经过其他障碍的方案即可,O(c^2)转移即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 typedef long long ll;
 7 using namespace std;
 8 const int mo=110119;
 9 struct node{ll x,y;} a[110];
10 int f[110],jc[mo+1],ni[mo+1];
11 ll n,m;
12 int t,tt;
13 bool cmp(node a,node b)
14 {
15   if (a.x==b.x) return a.y<b.y;
16   return a.x<b.x;
17 }
18 
19 ll quick(ll x,int y)
20 {
21   ll s=1;
22   while (y)
23   {
24     if (y&1) s=s*x%mo;
25     x=x*x%mo; y>>=1;
26   }
27   return s;
28 }
29 
30 int c(int n,int m)
31 {
32   if (n<0||m<0||m>n) return 0;
33   else return 1ll*jc[n]*ni[m]%mo*ni[n-m]%mo;
34 }
35 
36 int lucas(ll n,ll m)
37 {
38   if (n<0||m<0||m>n) return 0;
39   int ans=1;
40   while (n||m)
41   {
42     ans=1ll*ans*c(n%mo,m%mo)%mo;
43     n/=mo; m/=mo;
44   }
45   return ans;
46 }
47 
48 int main()
49 {
50   jc[0]=1; ni[0]=1;
51   for (int i=1; i<mo; i++)
52   {
53     jc[i]=1ll*jc[i-1]*i%mo;
54     ni[i]=quick(jc[i],mo-2);
55   }
56   while (scanf("%lld%lld%d",&n,&m,&t)!=EOF)
57   {
58     for (int i=1; i<=t; i++) scanf("%lld%lld",&a[i].x,&a[i].y);
59     a[++t]=(node){n,m};
60     sort(a+1,a+t+1,cmp);
61     memset(f,0,sizeof(f));
62     for (int i=1; i<=t; i++)
63     {
64       if ((a[i].x+a[i].y-2)%3) continue;
65       else f[i]=lucas((a[i].x+a[i].y-2)/3,(2ll*a[i].x-a[i].y-1)/3);
66       for (int j=1; j<i; j++)
67       {
68         if (a[i].x<a[j].x||a[i].y<a[j].y||(a[i].x+a[i].y-a[j].x-a[j].y)%3) continue;
69         f[i]=(f[i]-1ll*f[j]*lucas((a[i].x+a[i].y-a[j].x-a[j].y)/3,(2ll*(a[i].x-a[j].x)-(a[i].y-a[j].y))/3)%mo+mo)%mo;
70       }
71     }
72     printf("Case #%d: %d\n",++tt,f[t]);
73   }
74   return 0;
75 }
View Code

 

posted on 2016-08-25 14:40  acphile  阅读(166)  评论(0编辑  收藏  举报