题目链接: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. C读取文件

    C读取文件,这种写法不会多一行. #include "stdafx.h" #include <vector> using namespace std; struct P ...

  2. checkbox的完美用户体验(转)

    如需查看效果-->自行建个html文件,或者-->原文:http://bbs.blueidea.com/thread-2711834-1-7.html 最常见的checkbox的使用: & ...

  3. 查看PostgreSQL版本,编译器版本号

    [postgres@localhost bin]$ ./psql -h localhostpsql (9.4.5)Type "help" for help. postgres=# ...

  4. html 字体加粗

    <font style="font-weight: bold;">无敌小昆虫</font> <font>无敌小昆虫</font> f ...

  5. SQL 过滤 having

    select * from emp --having 对分组之后使用 --输出部门号 和 部门的平均工资 并且 平均工资 > 2000 select deptno, avg(sal) as &q ...

  6. php setcookie(name, value, expires, path, domain, secure) 参数详解

    setcookie() 定义一个和其余的 HTTP 标头一起发送的 cookie.和其它标头一样,cookie 必须在脚本的任何其它输出之前发送(这是协议限制).这 需要将本函数的调用放到任何输出之前 ...

  7. SPOJ COT2 Count on a tree II(树上莫队)

    题目链接:http://www.spoj.com/problems/COT2/ You are given a tree with N nodes.The tree nodes are numbere ...

  8. Tomcat8.5

    说明:Tomcat服务器上一个符合J2EE标准的Web服务器,在tomcat中无法运行EJB程序,如果要运行可以选择能够运行EJB程序的容器WebLogic,WebSphere,Jboss等Tomca ...

  9. Mac配置环境变量(Java,Android,Gradle,Maven,Hosts)

    JAVA_HOME 配置环境变量 # 使用vim打开.bash_profile文件,加入java环境变量 $ vim .bash_profile export JAVA_HOME=$(/usr/lib ...

  10. MVC4 导出word

    添加程序包 DocX using System.IO;using Novacode; /// <summary> /// 导出Word /// </summary> publi ...