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, 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)的更多相关文章
- HDU 5794 - A Simple Chess
HDU 5794 - A Simple Chess题意: 马(象棋)初始位置在(1,1), 现在要走到(n,m), 问有几种走法 棋盘上有r个障碍物, 该位置不能走, 并规定只能走右下方 数据范围: ...
- 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 ...
- hdu-5794 A Simple Chess(容斥+lucas+dp)
题目链接: A Simple Chess Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Ot ...
- 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 ...
- HDU5794 A Simple Chess 容斥+lucas
分析:转自http://blog.csdn.net/mengzhengnan/article/details/47031777 一点感想:其实这个题应该是可以想到的,但是赛场上并不会 dp[i]的定义 ...
- HDU 5794 A Simple Chess(杨辉三角+容斥原理+Lucas定理)
题目链接 A Simple Chess 打表发现这其实是一个杨辉三角…… 然后发现很多格子上方案数都是0 对于那写可能可以到达的点(先不考虑障碍点),我们先叫做有效的点 对于那些障碍,如果不在有效点上 ...
- HDU 5794 A Simple Chess ——(Lucas + 容斥)
网上找了很多人的博客,都看不太懂,还是大力学长的方法好. 要说明的一点是,因为是比较大的数字的组合数再加上mod比较小,因此用Lucas定理求组合数. 代码如下(有注释): #include < ...
- HDU 5794 A Simple Chess (Lucas + dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794 多校这题转化一下模型跟cf560E基本一样,可以先做cf上的这个题. 题目让你求一个棋子开始在( ...
- HDU 5794 A Simple Chess Lucas定理+dp
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5794 题意概述: 给出一个N*M的网格.网格上有一些点是障碍,不能经过.行走的方式是向右下角跳马步.求 ...
随机推荐
- Android应用程序中应用图标和名字的设置
在AndroidManifest.xml文件中设android:icon和 android:label指定名字和图标的位置,如: <application android:icon=" ...
- 【转载】Morris遍历二叉树 & BST(二叉搜索树) Traverse & 空间O(1) 时间O(n)
因为做一道Leetcode的题目(前面博客有:link),需要用Space O(1)空间复杂度来中序遍历树, 看了Discuss,也上网搜了一下,发现空间O(1)可以用 Morris遍历的方法.方法介 ...
- Jeally Bean中MonekyRunner 帮助文件
基于4.2的SDK导出来的MonkeyRunner的最新帮助,这个版本对MonkeyView和MonkeyRect有了很大的加强,在MonkeyRunner的易用性上有了很大的提高. 对于导出Monk ...
- 基于XMPP的即时通信系统的建立(四)— 协议详解
Presence 在XMPP协议中,我们使用presence来获取用户是否已经上线以及是否可以通信的状态. 为了能够知道自己联系人的状态以及让联系人知道自己的状态,用户上线后需要订阅联系人的状态,联系 ...
- ASP.NET MVC 学习8、Controller中的Detail和Delete方法
参考:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/examining-the-details-and ...
- 简单分析什么是SQL注入漏洞
现在很多人在入侵的过程中基本都是通过SQL注入来完成的,但是有多少人知道为什么会有这样的注入漏洞呢?有的会随口说着对于字符的过滤不严造成的.但是事实是这样吗?我们学这些,不仅要知其然,更要知其所以然! ...
- codeforces 333B - Chips
注意:横向纵向交叉时,只要两条边不是正中的边(当n&1!=1),就可以余下两个chip. 代码里数组a[][]第二维下标 0表示横向边,1表示纵向边. #include<stdio.h& ...
- C#进程启动程序,并禁止原窗口操作
Process myProcess = new Process(); myProcess.StartInfo.FileName = exeName; myP ...
- 载入在线jQuery库
以百度库为例 <script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script&g ...
- Delphi 为什么它提示PCHAR是不安全的类型呢 Unsafe type 'PChar'
DELPHI7已经考虑到了移植到点NET的问题,在点NET里,指针是不安全的.至于为什么有的人遇到,有的人没有遇到,那是因为各人的编译选项不同.在Project菜单下选Options“Compiler ...