zoukankan      html  css  js  c++  java
  • HDU 5794

    HDU 5794 - A Simple Chess
    题意:

      马(象棋)初始位置在(1,1), 现在要走到(n,m), 问有几种走法

      棋盘上有r个障碍物, 该位置不能走, 并规定只能走右下方

      

      数据范围: ( 1 ≤ n,m ≤10^18, 0 ≤ r ≤100 )
        
    分析:

      分析不存在障碍物时的走法规律:
        
                     (1,1)                      1
                  (2,3) (3,2)                      1   1
               (3,5) (4,4) (5,3)              1   2   1
            (4,7) (5,6) (6,5) (7,4)       1   3   3   1
                    ......               ......
            发现走法规律是一个斜着的杨辉三角, 即i层第j个的走法数为: C[i,j-1] (组合数)

       那么根据换算, 层数 = (x+y+1)/3 - 1 , 个数 = x - (x+y+1)/3

       即可得到无障碍物时,(m,n)点的路径数
        
        
        分析障碍物的贡献与障碍物之间的相互影响:

        障碍物(x,y)的贡献 = (1,1)到(x,y)的路径数 * (x,y)到(n,m)的路径数, 后者通过相对位置(平移)计算

        障碍物之间的影响, 即应去掉的重复部分, 也如此计算
        
            
        因为n,m数据范围大, 故计算组合数应用 LUCAS定理

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 using namespace std;
      6 #define LL long long
      7 const LL MOD = 110119;
      8 long long fac[MOD];
      9 //求a^n % MOD的值
     10 template<class T1, class T2>
     11 T1 QuickPow(T1 x, T2 n, T1 MOD) 
     12 {  
     13     T1 ans = 1;
     14     while (n) 
     15     {  
     16         if (n & 1) ans = (ans * x) % MOD;
     17         x = (x * x) % MOD;
     18         n >>= 1;
     19     }  
     20     return ans;  
     21 }
     22 //组合数
     23 //参数为C(n, m) % p (p为质数)
     24 //fac[i]表示i! % p
     25 template<class T, class Type>
     26 T C(Type n, Type m, T p) 
     27 {
     28     if (n < m) return 0;
     29     T x = fac[n], y = fac[n-m] * fac[m] % p;
     30     return x * QuickPow(y, p - 2, p) % p;
     31 }
     32 //生成i! % p (i = 0->p-1)
     33 //配合Lucas定理使用
     34 template<class T>
     35 void ProFac(T *fac, T p) 
     36 {
     37     fac[0] = 1;
     38     for (int i = 1; i < (int)p; i++)
     39         fac[i] = fac[i-1] * i % p;
     40 }
     41 //Lucas定理
     42 //求C(n, m) % p (n, m可以很大, p最大可为1e5, p为质数)
     43 //后面两个参数内部使用,不必考虑
     44 template<class T>
     45 T Lucas(T n, T m, T p) 
     46 {
     47     if (m == 0)  return 1LL;
     48     else 
     49     {
     50         T res = C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
     51         return res;
     52     }
     53 }
     54 
     55 
     56 inline bool change(LL x,LL y, LL &m,LL &n) //将(x,y) 转为 C[b][a]
     57 {
     58     if((x + y + 1) % 3 != 0 ) return 0;
     59     LL a = (x + y + 1) / 3;
     60     if(x < a || y < a) return 0;
     61     m = x - a;
     62     n = a - 1;
     63     return 1;
     64 }
     65 
     66 struct CC
     67 {
     68     LL x, y, a, b;
     69 }g[105];
     70 LL n, m, a, b;
     71 int r, tot;
     72 LL gx[105], gy[105], val[105];
     73 LL ans;
     74 
     75 bool cmp(CC a, CC b) 
     76 {
     77     return a.b < b.b;
     78 }
     79 bool flag;
     80 int main()
     81 {
     82     ProFac(fac, MOD);
     83     int tt = 1;
     84     while (~scanf("%lld%lld%d",&n,&m,&r))
     85     {
     86         flag = 0;
     87         for (int i = 1; i <= r; i++)
     88         {
     89             scanf("%lld%lld", &gx[i], &gy[i]);
     90             if(gx[i] == n && gy[i] == m) flag = 1;
     91         }
     92         printf("Case #%d: ", tt++);
     93         if (flag || !change(n, m, a, b)) //障碍物在 n,m 点,或者不能跳到n,m 
     94         {
     95             puts("0"); continue;
     96         }
     97         tot = 0;
     98         for (int i = 1; i <= r; i++)
     99         {
    100             if (!change(n - gx[i] + 1,m - gy[i] + 1, g[tot].a, g[tot].b)) continue; //该位置不能影响到 n,m点 
    101             if (change(gx[i], gy[i], g[tot].a, g[tot].b)) // 有效障碍物点
    102             {
    103                 g[tot].x = gx[i], g[tot].y = gy[i];
    104                 tot++;
    105             }
    106         }
    107         ans = Lucas(b, a, MOD);//C[b][a]
    108         sort(g, g + tot, cmp);
    109         for (int i = 0; i < tot; i++)
    110         {
    111             val[i] = Lucas(g[i].b, g[i].a, MOD);//到每个障碍物的的路径数 
    112         }
    113         for (int i = 0; i < tot; i++)
    114         {
    115             LL a1, b1, tmp;
    116              if (!change(n - g[i].x + 1, m - g[i].y + 1, a1, b1) ) continue;
    117             tmp = Lucas(b1, a1, MOD);
    118             ans = (ans + MOD - (val[i] * tmp % MOD )) % MOD;//减去障碍物贡献 
    119             for (int j = i + 1; j < tot; j++)
    120             {
    121                 if ( !change(g[j].x - g[i].x + 1, g[j].y - g[i].y + 1, a1, b1) ) continue;
    122                 tmp = Lucas(b1, a1, MOD);
    123                 val[j] = (val[j] + MOD - (val[i] * tmp % MOD )) % MOD; //减去障碍物之间的影响 
    124             }
    125         }
    126         printf("%lld
    ", ans);
    127     }
    128 }
    我自倾杯,君且随意
  • 相关阅读:
    Java 借助poi操作PDF工具类
    【ES】Java High Level REST Client 使用示例(增加修改)
    数据库表结构查询SQL
    MySQL windows中的存储备份
    jenkins + Ansible Plugin + ansi-color 让结果显示颜色
    jenkins 构建历史 显示版本号
    python 2.7.11 环境安装
    ansible 安装和使用
    豌豆夹Redis解决方案Codis安装使用
    Spark on Mesos部署
  • 原文地址:https://www.cnblogs.com/nicetomeetu/p/5741800.html
Copyright © 2011-2022 走看看