HDU 5794 A Simple Chess Lucas定理+dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794

 

题意概述:
  给出一个N*M的网格。网格上有一些点是障碍,不能经过。行走的方式是向右下角跳马步。求有多少种方案可以从(1,1)走到(N,M)。
  多组数据,组数不超过25。N,M<=1e18。

 

分析:

  还是水题。。。(我写这个的原因只是因为我第一次用lucas)分析一下可以发现横跳和纵跳各自的步数是确定的,所以变成了一个组合数问题。

  当有障碍的时候按照第一次碰到的障碍分类,先把棋盘当成完全没有障碍,然后扣掉这些方案即可。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<cctype>
12 using namespace std;
13 const int mo=110119;
14 typedef long long LL;
15 
16 LL N,M,R;
17 int inv[mo],J[mo],Ji[mo];
18 struct XY{
19     LL x,y;
20     friend bool operator < (XY a,XY b){
21         return a.x<b.x||a.x==b.x&&a.y<b.y;
22     }
23     friend bool operator == (XY a,XY b){
24         return a.x==b.x&&a.y==b.y;
25     }
26 }p[105];
27 int f[105];
28 
29 int Lucas(LL x,LL y)
30 {
31     if(x<y) return 0;
32     if(x<mo&&y<mo) return 1ll*J[x]*Ji[x-y]%mo*Ji[y]%mo;
33     return 1ll*Lucas(x/mo,y/mo)*Lucas(x%mo,y%mo)%mo;
34 }
35 void ready()
36 {
37     inv[1]=1;
38     for(int i=2;i<mo;i++)
39         inv[i]=1ll*inv[mo%i]*(mo-mo/i)%mo;
40     J[0]=1,Ji[0]=1;
41     for(int i=1;i<mo;i++){
42         J[i]=1ll*J[i-1]*i%mo;
43         Ji[i]=1ll*Ji[i-1]*inv[i]%mo;
44     }
45 }
46 int solve(LL n,LL m)
47 {
48     if((2*n-m-1)<0||(2*n-m-1)%3||(2*m-n-1)<0||(2*m-n-1)%3) return 0;
49     LL a=(2*m-n-1)/3,b=(2*n-m-1)/3;
50     return Lucas(a+b,b);
51 }
52 int main()
53 {
54     ready();
55     int T=0;
56     while(cin>>N>>M>>R){
57         int ans=solve(N,M);
58         if(R){
59             for(int i=1;i<=R;i++)
60                 cin>>p[i].x>>p[i].y;
61             sort(p+1,p+R+1);
62             R=unique(p+1,p+R+1)-p-1;
63             memset(f,0,sizeof(f));
64             for(int i=1;i<=R;i++){
65                 f[i]=solve(p[i].x,p[i].y);
66                 for(int j=1;j<i;j++)if(p[j].x<p[i].x&&p[j].y<p[i].y)
67                     f[i]=(f[i]-1ll*f[j]*solve(p[i].x-p[j].x+1,p[i].y-p[j].y+1)%mo+mo)%mo;
68             }
69             for(int i=1;i<=R;i++)
70                 ans=(ans-1ll*f[i]*solve(N-p[i].x+1,M-p[i].y+1)%mo+mo)%mo;
71         }
72         cout<<"Case #"<<++T<<": "<<ans<<'\n';
73     }
74     return 0;
75 }
View Code

 

posted @ 2018-03-23 16:29  KKKorange  阅读(235)  评论(0编辑  收藏  举报