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
  • 相关阅读:
    黑马程序员--C语言基础之--数组、指针的基础知识
    黑马程序员--C语言基础之--变量、内部函数与外部函数
    黑马程序员--C语言基础之--printf函数
    黑马程序员--C语言基础之--scanf函数
    黑马程序员--C语言基础之--数据类型
    鉴定一张图片是否处理过
    图解JQUERY尺寸及位置定义
    谈谈对“渐进增强与平稳退化“的理解
    理解 JavaScript 作用域和作用域链
    编写更好的jQuery代码的建议
  • 原文地址:https://www.cnblogs.com/KKKorange/p/8631061.html
Copyright © 2011-2022 走看看