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定理

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
const LL MOD = ;
long long fac[MOD];
//求a^n % MOD的值
template<class T1, class T2>
T1 QuickPow(T1 x, T2 n, T1 MOD)
{
T1 ans = ;
while (n)
{
if (n & ) ans = (ans * x) % MOD;
x = (x * x) % MOD;
n >>= ;
}
return ans;
}
//组合数
//参数为C(n, m) % p (p为质数)
//fac[i]表示i! % p
template<class T, class Type>
T C(Type n, Type m, T p)
{
if (n < m) return ;
T x = fac[n], y = fac[n-m] * fac[m] % p;
return x * QuickPow(y, p - , p) % p;
}
//生成i! % p (i = 0->p-1)
//配合Lucas定理使用
template<class T>
void ProFac(T *fac, T p)
{
fac[] = ;
for (int i = ; i < (int)p; i++)
fac[i] = fac[i-] * i % p;
}
//Lucas定理
//求C(n, m) % p (n, m可以很大, p最大可为1e5, p为质数)
//后面两个参数内部使用,不必考虑
template<class T>
T Lucas(T n, T m, T p)
{
if (m == ) return 1LL;
else
{
T res = C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
return res;
}
} inline bool change(LL x,LL y, LL &m,LL &n) //将(x,y) 转为 C[b][a]
{
if((x + y + ) % != ) return ;
LL a = (x + y + ) / ;
if(x < a || y < a) return ;
m = x - a;
n = a - ;
return ;
} struct CC
{
LL x, y, a, b;
}g[];
LL n, m, a, b;
int r, tot;
LL gx[], gy[], val[];
LL ans; bool cmp(CC a, CC b)
{
return a.b < b.b;
}
bool flag;
int main()
{
ProFac(fac, MOD);
int tt = ;
while (~scanf("%lld%lld%d",&n,&m,&r))
{
flag = ;
for (int i = ; i <= r; i++)
{
scanf("%lld%lld", &gx[i], &gy[i]);
if(gx[i] == n && gy[i] == m) flag = ;
}
printf("Case #%d: ", tt++);
if (flag || !change(n, m, a, b)) //障碍物在 n,m 点,或者不能跳到n,m
{
puts(""); continue;
}
tot = ;
for (int i = ; i <= r; i++)
{
if (!change(n - gx[i] + ,m - gy[i] + , g[tot].a, g[tot].b)) continue; //该位置不能影响到 n,m点
if (change(gx[i], gy[i], g[tot].a, g[tot].b)) // 有效障碍物点
{
g[tot].x = gx[i], g[tot].y = gy[i];
tot++;
}
}
ans = Lucas(b, a, MOD);//C[b][a]
sort(g, g + tot, cmp);
for (int i = ; i < tot; i++)
{
val[i] = Lucas(g[i].b, g[i].a, MOD);//到每个障碍物的的路径数
}
for (int i = ; i < tot; i++)
{
LL a1, b1, tmp;
if (!change(n - g[i].x + , m - g[i].y + , a1, b1) ) continue;
tmp = Lucas(b1, a1, MOD);
ans = (ans + MOD - (val[i] * tmp % MOD )) % MOD;//减去障碍物贡献
for (int j = i + ; j < tot; j++)
{
if ( !change(g[j].x - g[i].x + , g[j].y - g[i].y + , a1, b1) ) continue;
tmp = Lucas(b1, a1, MOD);
val[j] = (val[j] + MOD - (val[i] * tmp % MOD )) % MOD; //减去障碍物之间的影响
}
}
printf("%lld\n", ans);
}
}

HDU 5794 - A Simple Chess的更多相关文章

  1. HDU 5794 A Simple Chess dp+Lucas

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5794 A Simple Chess Time Limit: 2000/1000 MS (Java/O ...

  2. HDU 5794 A Simple Chess (容斥+DP+Lucas)

    A Simple Chess 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5794 Description There is a n×m board ...

  3. HDU 5794 A Simple Chess(杨辉三角+容斥原理+Lucas定理)

    题目链接 A Simple Chess 打表发现这其实是一个杨辉三角…… 然后发现很多格子上方案数都是0 对于那写可能可以到达的点(先不考虑障碍点),我们先叫做有效的点 对于那些障碍,如果不在有效点上 ...

  4. HDU 5794 A Simple Chess (Lucas + dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794 多校这题转化一下模型跟cf560E基本一样,可以先做cf上的这个题. 题目让你求一个棋子开始在( ...

  5. HDU 5794 A Simple Chess Lucas定理+dp

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794 题意概述: 给出一个N*M的网格.网格上有一些点是障碍,不能经过.行走的方式是向右下角跳马步.求 ...

  6. HDU 5794 A Simple Chess ——(Lucas + 容斥)

    网上找了很多人的博客,都看不太懂,还是大力学长的方法好. 要说明的一点是,因为是比较大的数字的组合数再加上mod比较小,因此用Lucas定理求组合数. 代码如下(有注释): #include < ...

  7. HDU 5794 - A Simple Nim

    题意:    n堆石子,先拿光就赢,操作分为两种:        1.任意一堆中拿走任意颗石子        2.将任意一堆分成三小堆 ( 每堆至少一颗 )        分析:    答案为每一堆的 ...

  8. hdu5794 A Simple Chess 容斥+Lucas 从(1,1)开始出发,每一步从(x1,y1)到达(x2,y2)满足(x2−x1)^2+(y2−y1)^2=5, x2>x1,y2>y1; 其实就是走日字。而且是往(n,m)方向走的日字。还有r个障碍物,障碍物不可以到达。求(1,1)到(n,m)的路径条数。

    A Simple Chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  9. 2016暑假多校联合---A Simple Chess

    2016暑假多校联合---A Simple Chess   Problem Description There is a n×m board, a chess want to go to the po ...

随机推荐

  1. 【转载】ADO.NET与ORM的比较(4):EntityFramework实现CRUD

    [转载]ADO.NET与ORM的比较(4):EntityFramework实现CRUD 说明:个人感觉在Java领域大型开发都离不了ORM的身影,所谓的SSH就是Spring+Struts+Hiber ...

  2. Spark配置&启动脚本分析

    本文档基于Spark2.0,对spark启动脚本进行分析. date:2016/8/3 author:wangxl Spark配置&启动脚本分析 我们主要关注3类文件,配置文件,启动脚本文件以 ...

  3. 1010 Area

    题目要求面积和判断非相邻边不相交.和数学和几何有关系. #include <stdio.h> #include <math.h> #define MISS 0.0000001 ...

  4. WPF安装部署小结

    开机启动 右击"MySetup">>"视图">>"注册表",在"HKEY_LOCAL-MACHINE&qu ...

  5. MySQL--mysqldump的权限说明

    mysqldump 所需要的权限说明: 1.对于table 来说mysqldump 最少要有select 权限. 2.对于view 来说mysqldump 要有show view 权限. 3.对于tr ...

  6. HttpWebResponse类

    HttpWebResponse类的作用用于在客户端获取返回的响应的信息,还记得HttpResponse类吗?你是否在写B/S程序的时候,经常用到Response.Write()呢? HttpRespo ...

  7. 过滤ASCII码中的不可见字符, ASCII三部分, 各控制字符详解, 去^@,^M

    今天产品部同事报告了一个BUG,经过调试发现,由于用户输入的字符串中,包含字符0x1E, 也就是”记录分隔符”(Record Separator, Notepad++ 显示为[RS]),导致JavaS ...

  8. shell printf格式化输出语句

    printf 命令用于格式化输出, 是echo命令的增强版.它是C语言printf()库函数的一个有限的变形,并且在语法上有些不同. 注意:printf 由 POSIX 标准所定义,移植性要比 ech ...

  9. ## GridView 布局:item设置的高度和宽度不起作用、自动适配列数、添加Header和Footer ##

    一.item设置的高度和宽度不起作用 转自:http://www.cnblogs.com/0616--ataozhijia/p/6031875.html [Android Pro] listView和 ...

  10. Jquery EasyUI修改行背景的两种方式

    1.数据加载完成不请求后台的做法 方式一: //更改表格行背景 function changeLineStyle(index){ var rows=$("#alertGird"). ...