zoukankan      html  css  js  c++  java
  • 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<<'
    ';
    73     }
    74     return 0;
    75 }
    View Code
  • 相关阅读:
    restful架构风格设计准则(四)资源表示和资源访问
    洛谷P2178 [NOI2015]品酒大会(后缀自动机 线段树)
    HDU 6138 Fleet of the Eternal Throne(后缀自动机)
    BZOJ1278: 向量vector(计算几何 随机化乱搞)
    BZOJ2564: 集合的面积(闵可夫斯基和 凸包)
    POJ 1113 Wall(思维 计算几何 数学)
    POJ 3304 Segments(直线与线段相交)
    洛谷P1742 最小圆覆盖(计算几何)
    洛谷P4555 [国家集训队]最长双回文串(manacher 线段树)
    洛谷P3193 [HNOI2008]GT考试(dp 矩阵乘法)
  • 原文地址:https://www.cnblogs.com/KKKorange/p/8631061.html
Copyright © 2011-2022 走看看