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. Regex Failure - Bug Fixing #2

    http://www.codewars.com/kata/55c423ecf847fbcba100002b/train/csharp Oh no, Timmy's received some hate ...

  2. ASCII 字符代码表

  3. li添加浮动时不能完全包裹的方法

    <html> <head> <meta http-equiv="Content-Type" content="text/html;chars ...

  4. js 写成类的形式 js 静态变量 js方法 属性 json类

    function ClassStudentList() { //[{"Cid":"0d","Students":[{"Sid&qu ...

  5. Java [Leetcode 318]Maximum Product of Word Lengths

    题目描述: Given a string array words, find the maximum value of length(word[i]) * length(word[j]) where ...

  6. Java基础——异常处理

    异常的层次结构 所有的异常类都是 java.lang.Exception 类的子类型.异常类都是 Throwable 类的子类.除了异常类 Error 类也是由 Throwable 类产生的的子类1. ...

  7. hihocoder 1233 Boxes

    题意:类汉诺塔的一个东西……移动规则与汉诺塔一样,但初始状态为题目中给出的每根棍上一个盘子,目标状态为盘子在棍上按大小顺序排列,盘子只能在相邻的棍儿上移动. 解法:广搜并打表记录从目标状态到所有可能的 ...

  8. android改变字体的颜色的三种方法

    写文字在Android模拟器中的方法 法一: main.xml配置文件: <TextView android:id="@+id/tv" android:layout_widt ...

  9. UiThread DEMO

    import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import android.a ...

  10. 翻译【ElasticSearch Server】第一章:开始使用ElasticSearch集群(3)

    运行ElasticSearch(Running ElasticSearch) 让我们运行我们的第一个实例.转到bin目录并从命令行运行以下命令: ./elasticsearch –f (Linux o ...