题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5794

题意:让一个棋子从(1,1)走到(n,m),要求像马一样走日字型并只能往右下角走。里面还有r个障碍点不能经过或者到达,问有多少种走法可以走到(n,m)。

思路:画个图可以发现走的点像一个斜着的杨辉三角。所以可以得到一个从点 i 走到点 j 的路径数是一个组合数。

大概就是长这样,杨辉三角的每个点的数如下。

1

1       1

1      2      1

1       3      3      1

1      4       6      4      1

1       5      10      10      5      1

1      6      15      20      15      6      1

1      7      21      35      35      21      7      1

找到规律:路径数为C(在这一步的位置,走过的步数)。走过的步数是当前的点 i 坐标(x,y),(x+y)/3就是步数了。当前的位置是min(x,y)-步数。这里的步数就相当于三角的层数。

首先对全部障碍从小到大进行排序,对于每个障碍 i,求出从(1,1)走到其的路径总数,减去之前的障碍(0 <= j < i)可以走到现在的障碍的路径总数(dp[i] -= dp[j] * 从点 j 走到点 i 的路径数)。组合数的计算要用到Lucas定理进行计算。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <iostream>
#include <stack>
using namespace std;
#define MOD 110119
typedef long long LL;
struct node
{
LL x, y;
}p[];
LL dp[];
LL f[MOD+];
/*
dp[i]一开始表示从(0, 0)走到第i个点的路径数
后面要减去如果前面有障碍,那么会有一部分路径是不能走的
减去的路径数为分别为第j个点(0<=j<i)走到第i个点的路径数*dp[j]
*/ bool cmp(const node &a, const node &b)
{
if(a.x == b.x) return a.y < b.y;
return a.x < b.x;
} void biao() //打出阶乘表
{
f[] = f[] = ;
for(int i = ; i <= MOD; i++) {
f[i] = f[i-] * i % MOD;
}
} LL quick_pow(LL a, LL b)
{
a %= MOD, b %= MOD;
LL ans = ;
while(b) {
if(b & ) ans = ans * a % MOD;
a = a * a % MOD;
b >>= ;
}
return ans;
} LL C(LL n, LL m)
{
if(m > n) return ;
if(m < ) return ;
LL ans = ;
ans = ans * f[n] % MOD * quick_pow(f[m] * f[n-m] % MOD, MOD - ) % MOD;
return ans;
} LL Lucas(LL n, LL m)
{
if(m == ) return ;
return C(n % MOD, m % MOD) % MOD * Lucas(n / MOD, m / MOD) % MOD;
} int main()
{
LL n, m, r;
int cas = ;
biao();
while(~scanf("%I64d%I64d%I64d", &n, &m, &r)) {
memset(dp, , sizeof(dp));
bool flag = ;
for(int i = ; i < r; i++) {
scanf("%I64d%I64d", &p[i].x, &p[i].y);
if(p[i].x == n && p[i].y == m) flag = ;
p[i].x--, p[i].y--;
}
sort(p, p + r, cmp);
p[r].x = n - , p[r].y = m - ; //把目标点加入
printf("Case #%d: ", ++cas);
if(flag || (p[r].x + p[r].y) % != ) { //如果障碍在目标点上或者不能走到目标点
puts(""); continue;
}
for(int i = ; i <= r; i++) {
if((p[i].x + p[i].y) % == ) { //如果这个障碍是可以走到的
LL a = (p[i].x + p[i].y) / ; //第几层
LL b = min(p[i].x, p[i].y) - a; //位置
dp[i] = Lucas(a, b); //类似于杨辉三角的组合数
for(int j = ; j < i; j++) {
if(p[j].y >= p[i].y || p[j].x >= p[i].x) continue; //题目要求只能往右下角走
LL xx = (p[i].x - p[j].x);
LL yy = (p[i].y - p[j].y);
if((xx + yy) % == ) { //要能够从j点走到i点
LL aa = (xx + yy) / ;
LL bb = min(xx, yy) - aa; //减去可以从j点走到i点的路径数
dp[i] -= (Lucas(aa, bb) * dp[j]) % MOD;
dp[i] = (dp[i] + MOD) % MOD;
}
}
}
}
printf("%I64d\n", dp[r]);
}
return ;
}

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

  1. HDU 3076:ssworld VS DDD(概率DP)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=3076 ssworld VS DDD Problem Description   One day, s ...

  2. HDU 5616:Jam's balance(背包DP)

    http://acm.hdu.edu.cn/showproblem.php?pid=5616 题意:有n个物品,每个重量为w[i],有一个天平,你可以把物品放在天平的左边或者右边,接下来m个询问,问是 ...

  3. 【HDU 5647】DZY Loves Connecting(树DP)

    pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...

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

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

  5. HDU 5795:A Simple Nim(博弈)

    http://acm.hdu.edu.cn/showproblem.php?pid=5795 A Simple Nim Problem Description   Two players take t ...

  6. HDU 4315:Climbing the Hill(阶梯博弈)

    http://acm.hdu.edu.cn/showproblem.php?pid=4315 题意:有n个人要往坐标为0的地方移动,他们分别有一个位置a[i],其中最靠近0的第k个人是king,移动的 ...

  7. HDU 6215:Brute Force Sorting(链表+队列)

    题目链接 题意 给出一个长度为n的数组,每次操作都要删除数组里面非递增的元素,问最终的数组元素有什么. 思路 容易想到用链表模拟删除,但是不能每次都暴力枚举,这样复杂度O(N^2).想到每次删除元素的 ...

  8. UVA-11584:Partitioning by Palindromes(基础DP)

    今天带来一个简单的线性结构上的DP,与上次的照明系统(UVA11400)是同一种类型题,便于大家类比.总结.理解,但难度上降低了. We say a sequence of characters is ...

  9. Codeforces Gym100623J:Just Too Lucky(数位DP)

    http://codeforces.com/gym/100623/attachments 题意:问1到n里面有多少个数满足:本身被其各个数位加起来的和整除.例如120 % 3 == 0,111 % 3 ...

随机推荐

  1. SQLserver 表字段修改语句

    增加字段 ) 删除字段 ALTER TABLE table_NAME DROP COLUMN column_NAME 修改字段类型 ALTER TABLE table_name ALTER COLUM ...

  2. Map的基本用法(Java)

    package home.collection.arr; import java.awt.Window.Type; import java.util.ArrayList; import java.ut ...

  3. WPF 基础面试题及答案(一)

    一 · WPF由哪两部分组成? wpf 由两个主要部分 组成:引擎和编程框架. 1 引擎.wpf引擎是基于窗体的应用程序 图形 视频 音频和文档提供了一个单一的运行时库.重要的是WPF基于矢量的呈现引 ...

  4. 对jsp可见域的变量感悟

    page  变量当前页面有效 reqeust 某次请求中的变量有效 session 某次会话中的变量有效 application 全站有效 page<request<session< ...

  5. 关于解决读取导入excel某列数字过长的科学计数法格式

    因为 客户 需要导入 虚拟商品的卡号 excel已经是文本形式的单元格格式了 但是 到后台 java代码去获取的时候 仍然是 科学计数法格式 先找到以下资料做参考:http://love-66521. ...

  6. Java基础之处理事件——实现低级事件监听器(Sketcher 2 implementing a low-level listener)

    控制台程序. 定义事件监听器的类必须实现监听器接口.所有的事件监听器接口都扩展了java.util.EventListener接口.这个接口没有声明任何方法,仅仅用于表示监听器对象.使用EventLi ...

  7. Java基础之读文件——使用通道随机读取文件(RandomFileRead)

    import java.nio.file.*; import java.nio.channels.FileChannel; import java.io.IOException; import jav ...

  8. GTA项目 三, 使用 bootstrap table展示界面,使得data和UI分离

    /** bootstrap-table - v1.5.0 - 2014-12-12* https://github.com/wenzhixin/bootstrap-table* Copyright ( ...

  9. Codeforce Round #210 Div2

    A:对角线为k其他为0 B:利用两个相邻的数一定gcd为1和1与任何数gcd为1错k个位就行了 C:不会做操蛋,好像是因为上一层的始终小于下一层的 好吧C又研究了一下,是个贪心题,不符合的情况先科不考 ...

  10. How to export a template in Visual Studio?

    Create a customize template file: 1.template arguments introduction like: 上图只是其中一部分,更多请查看文后的参考资源 tem ...