A Simple Chess

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5794

Description


There is a n×m board, a chess want to go to the position
(n,m) from the position (1,1).
The chess is able to go to position (x2,y2) from the position (x1,y1), only and if only x1,y1,x2,y2 is satisfied that (x2−x1)2+(y2−y1)2=5, x2>x1, y2>y1.
Unfortunately, there are some obstacles on the board. And the chess never can stay on the grid where has a obstacle.
I want you to tell me, There are how may ways the chess can achieve its goal.

Input


The input consists of multiple test cases.
For each test case:
The first line is three integers, n,m,r,(1≤n,m≤1018,0≤r≤100), denoting the height of the board, the weight of the board, and the number of the obstacles on the board.
Then follow r lines, each lines have two integers, x,y(1≤x≤n,1≤y≤m), denoting the position of the obstacles. please note there aren't never a obstacles at position (1,1).

Output


For each test case,output a single line "Case #x: y", where x is the case number, starting from 1. And y is the answer after module 110119.

Sample Input


1 1 0
3 3 0
4 4 1
2 1
4 4 1
3 2
7 10 2
1 2
7 1

Sample Output


Case #1: 1
Case #2: 0
Case #3: 2
Case #4: 1
Case #5: 5

Source


2016 Multi-University Training Contest 6


##题意:

在n*m的棋盘上,从左上角(1,1)走到右下角(n,m)有多少条路线.
每次只能向右下方走"L"型路线. (x,y) => (x+1,y+2) or (x+2, y+1);
棋盘上有n个(n

##题解:

问题一:如何计算路线数
如果不存在任何障碍,从点(x1,y1)到点(x2,y2):
①. 不能到达:由于走的是"L"型路线(类似象棋的马),所以有可能到不了.
每走一步实际上是移动了三个单位(包括上下方向),而起点到终点共有(x2-x1) + (y2-y1)个单位.
所以能走到的充分必要条件是:((x2-x1)+(y2-y1)) % 3 == 0 ; 且终点在起点的左下方(x2>x1 && y2>y1).
②. 如果能到达:走的步数是 step = (x2+y2-x1-y1) / 3.
走法有 "L"型{(x,y)=>(x+2,y+1)} 和 "倒L"型{(x,y)=>(x+1,y+2)} 两种.
无论怎么走都至少会在上下两方向上都减1. 所以上下两方向各剩下 s1=x2-x1-step 和 s2=y2-y1-step 个单位.
再用"L"型和"倒L"型去分配这剩下的单位. 即 C(s1+s2, s1) 或 C(s1+s2, s2).
(另解:先看成往右下走一格,再抉择往右还是往下.)
③. 由于坐标范围较大,而取模的p=110119较小且为质数.
所以这里用lucas公式来求组合数.
(一般的:数较小且mod较大时用逆元求组合数,数较大且mod较小时用lucas求组合数)
(由于上述公式中s1 s2有可能为负数,所以lucas里面一定要对负数组合数作特判) (论完美模版的重要性).

问题二:如何考虑障碍物
容斥 + DP:坐标范围较大,只能对障碍位置进行dp:
dp[i]: 从(1,1)到障碍i且不经过其他障碍的路线数.
转移方程:
dp[i] = (起点到障碍i的路线) - Σ(dp[j] * (障碍j到障碍i的路线))
(其中j为位于障碍i左上方的障碍,即j可以通过合法路径到达i. 因此处理时先对障碍坐标排序).

类似题目对比总结:
至今为止做过五个类似的题:
1. CF-560E [Gerald and Giant Chess](http://www.codeforces.com/problemset/problem/560/E)
每次只能往右或下走,方案数比较好求,逆元求组合数(坐标较小).
2. UVALive-6916 [Punching Robot](http://acm.hust.edu.cn/vjudge/contest/97671#problem/K)
每次只能往右或下走,方案数比较好求,Lucas求组合数(坐标较大).
3. Gym-100379J [Move the (p, q)-knight to the corner!](http://acm.hust.edu.cn/vjudge/contest/87224#problem/H)
这个题跟本题几乎一样,走"类L"型路线,Lucas求组合数.
4. NOIP1997-普及组 [街道](http://oj.tsinsen.com/A1110)
这个题是坐标较小(50*50),障碍是一个矩形区域,对非障碍位置DP+高精度即可.
5. HDU-5794 [本题](http://acm.hdu.edu.cn/showproblem.php?pid=5794)
走"L"型路线,Lucas求组合数.


##代码:
``` cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define eps 1e-8
#define maxn 150
#define mod 110119
#define inf 0x3f3f3f3f
#define mid(a,b) ((a+b)>>1)
#define IN freopen("in.txt","r",stdin);
using namespace std;

LL F[mod+10];

void init(LL p)

{

F[0] = 1;

for(int i = 1;i <= p;i++)

F[i] = F[i-1]i%p;

}

LL inv(LL a,LL m)

{

if(a == 1)return 1;

return inv(m%a,m)
(m-m/a)%m;

}

/初始化init(p),调用Lucas(m,n,p)计算C_m_n%p/

LL Lucas(LL n,LL m,LL p)

{

if(n < 0 || m < 0 || m > n)

return 0;

LL ans = 1;

while(n&&m)

{

LL a = n%p;

LL b = m%p;

if(a < b)return 0;

ans = ansF[a]%pinv(F[b]*F[a-b]%p,p)%p;

n /= p;

m /= p;

}

return ans;

}

LL get_ans(LL n, LL m)

{

return Lucas(m+n, m, mod);

}

LL m,n;

int k;

LL path[150];

struct node{

LL x,y;

bool operator < (const node& b)const {

if(x == b.x) return y < b.y;

return x < b.x;

}

}block[150];

int main(int argc, char const *argv[])

{

//IN;

init(mod);

int ca = 1;
while(scanf("%I64d %I64d %d", &n, &m, &k) != EOF)
{
memset(path, 0, sizeof(path));
memset(block, 0, sizeof(block));
for(int i=1; i<=k; i++){
scanf("%I64d %I64d", &block[i].x, &block[i].y);
}
block[k+1].x = n; block[k+1].y = m;
sort(block+1, block+k+2); for(int i=1; i<=k+1; i++) {
/*先求(1,1)到block_i的路线条数*/
LL step = block[i].x + block[i].y - 2;
if(step % 3) continue;
path[i] = get_ans(block[i].x - 1 - step/3, block[i].y - 1 - step/3); /*依次减去经过了其它障碍的路线数*/
for(int j=1; j<i; j++) {
LL step = block[i].x + block[i].y - block[j].x - block[j].y;
if(block[j].y > block[i].y || block[j].x > block[i].x || step % 3) continue; LL tmp = get_ans(block[i].x - block[j].x - step/3, block[i].y - block[j].y - step/3); path[i] = (path[i] + mod - (path[j] * tmp) % mod) % mod;
}
} printf("Case #%d: %I64d\n", ca++, path[k+1]%mod);
} return 0;

}

HDU 5794 A Simple Chess (容斥+DP+Lucas)的更多相关文章

  1. HDU 5794 - A Simple Chess

    HDU 5794 - A Simple Chess题意: 马(象棋)初始位置在(1,1), 现在要走到(n,m), 问有几种走法 棋盘上有r个障碍物, 该位置不能走, 并规定只能走右下方 数据范围: ...

  2. 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 ...

  3. hdu-5794 A Simple Chess(容斥+lucas+dp)

    题目链接: A Simple Chess Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Ot ...

  4. 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 ...

  5. HDU5794 A Simple Chess 容斥+lucas

    分析:转自http://blog.csdn.net/mengzhengnan/article/details/47031777 一点感想:其实这个题应该是可以想到的,但是赛场上并不会 dp[i]的定义 ...

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

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

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

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

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

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

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

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

随机推荐

  1. EBS报表输出文件格式控制

    具体使用方法:1.添加用户参数p_conc_request_id2.在BeforeReport trigger中添加srw.user_exit('FND SRWINIT');          和Af ...

  2. tranform-scale 缩小元素,移上去文字抖动

    元素缩小后,鼠标移上去之后文字会出现抖动, -webkit-transform:scale(0.5); 修复代码如下: *{ -webkit-backface-visibility: hidden; ...

  3. struts.custom.i18n.resources 如何配置多个资源文件?

    struts.custom.i18n.resources = resources1,resources2,resources3   配置properties文件

  4. UVA 11294 Wedding(2-sat)

    2-sat.不错的一道题,学到了不少. 需要注意这么几点: 1.题目中描述的是有n对夫妇,其中(n-1)对是来为余下的一对办婚礼的,所以新娘只有一位. 2.2-sat问题是根据必然性建边,比如说A与B ...

  5. UVA 550 Multiplying by Rotation (简单递推)

    题意:有些数字是可以这样的:abcd*k=dabc,例如179487 * 4 = 717948,仅仅将尾数7移动到前面,其他都不用改变位置及大小.这里会给出3个数字b.d.k,分别代表b进制.尾数.第 ...

  6. 转载RabbitMQ入门(2)--工作队列

    工作队列 (使用Java客户端) 在这第一指南部分,我们写了通过同一命名的队列发送和接受消息.在这一部分,我们将会创建一个工作队列,在多个工作者之间使用分布式时间任务. 工作队列(亦称:任务队列)背后 ...

  7. memcache的应用场景和实现原理

    面临的问题 对于高并发高访问的 Web应用程序来说,数据库存取瓶颈一直是个令人头疼的问题.特别当你的程序架构还是建立在单数据库模式,而一个数据池连接数峰 值已经达到500的时候,那你的程序运行离崩溃的 ...

  8. Android中FragmentPagerAdapter对Fragment的缓存(二)

    上一篇我们谈到了,当应用程序恢复时,由于FragmentPagerAdapter对Fragment进行了缓存的读取,导致其并未使用在Activity中新创建的Fragment实例.今天我们来看如何解决 ...

  9. c# List<int> 转 string 以及 string [] 转 List<int>

    List<int> 转 string : list<int>: 1,2,3,4,5,6,7  转换成字符串:“1,2,3,4,5,6,7” List<int> li ...

  10. Jedis的JedisSentinelPool源代码分析

    概述 Jedis是Redis官方推荐的Java客户端,更多Redis的客户端可以参考Redis官网客户端列表.Redis-Sentinel作为官方推荐的HA解决方案,Jedis也在客户端角度实现了对S ...