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

多校这题转化一下模型跟cf560E基本一样,可以先做cf上的这个题。

题目让你求一个棋子开始在(1,1),只能像马一样走且往右下方走,不经过坏点,有多少种走法能到达(n,m)点。

比如n=6, m=5 有两个坏点,模型转换 如下图:

转换成简单模型之后,只要把棋子可能经过的坏点存到结构体中,按照x与y从小到大排序。

dp[i]表示从起点到第i个坏点且不经过其他坏点的方案数。

dp[i] = Lucas(x[i], y[i]) - sum(dp[j]*Lucas(x[i]-x[j], y[i]-x[j])) , x[j] <= x[i] && y[j] <= y[i] //到i点所有的路径数目 - 经过其他点的路径数目

那我们把最后一个点也设成坏点,比如dp[final],那么dp[final]就是答案了

 //#pragma comment(linker, "/STACK:102400000, 102400000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
typedef pair <LL, LL> P;
const int N = 1e2 + ;
const LL mod = ;
struct data {
LL x, y;
bool operator <(const data& cmp) const {
return x == cmp.x ? y < cmp.y : x < cmp.x;
}
}q[N];
LL f[mod + ]; //阶乘
dp[N]; LL Pow(LL a , LL n , LL mod) {
LL res = ;
while(n) {
if(n & )
res = res * a % mod;
a = a * a % mod;
n >>= ;
}
return res;
} LL Comb(LL a , LL b , LL mod) {
if(a < b) {
return ;
}
if(a == b) {
return ;
}
return (f[a] * Pow(f[a - b]*f[b] % mod , mod - , mod)) % mod; //乘法逆元
} LL Lucas(LL n , LL m , LL mod) {
LL ans = ;
while(m && n && ans) {
ans = (ans * Comb(n % mod , m % mod , mod)) % mod;
n /= mod;
m /= mod;
}
return ans;
} bool judge(LL x, LL y) { //判断'马' 能否走到坏点
if(x > y)
swap(x, y);
LL dec = y - x;
if(dec > x || dec* > y || (x - dec) % != || (y - dec*) % != || x - dec != y - dec*)
return true;
return false;
} P get(LL x, LL y) { //得到模型的x和y
P res;
if(x > y) {
LL dec = x - y;
res.first = dec, res.second = ;
x -= dec * , y -= dec;
res.first += x / , res.second += y / ;
} else {
LL dec = y - x;
res.first = , res.second = dec;
x -= dec, y -= dec * ;
res.first += x / , res.second += y / ;
}
return res;
} int main()
{
int Case = ;
LL n, m;
int k;
f[] = ;
for(LL i = ; i <= mod; ++i)
f[i] = f[i - ] * i % mod;
while(scanf("%lld %lld %d", &n, &m, &k) != EOF) {
n--, m--;
for(int i = ; i <= k; ++i) {
scanf("%lld %lld", &q[i].x, &q[i].y);
q[i].x--, q[i].y--;
}
printf("Case #%d: ", Case++);
if(judge(n, m)) {
printf("0\n");
continue;
}
P temp = get(n, m);
n = temp.first, m = temp.second;
int index = ;
for(int i = ; i <= k; ++i) {
if(judge(q[i].x, q[i].y))
continue;
temp = get(q[i].x, q[i].y);
if(temp.first > n || temp.second > m)
continue;
q[++index].x = temp.first, q[index].y = temp.second;
}
sort(q + , q + index + );
q[++index].x = n, q[index].y = m;
memset(dp, , sizeof(dp));
for(int i = ; i <= index; ++i) {
LL sum = ;
for(int j = ; j < i; ++j) {
if(q[i].x >= q[j].x && q[i].y >= q[j].y) {
sum = (sum + dp[j]*Lucas(q[i].x - q[j].x - q[j].y + q[i].y, q[i].y - q[j].y, mod) % mod) % mod;
}
}
dp[i] = ((Lucas(q[i].x + q[i].y, q[i].y, mod) - sum) % mod + mod) % mod;
}
printf("%lld\n", dp[index]);
}
return ;
}

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

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

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

  2. HDU 5794 - A Simple Chess

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

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

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

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

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

  6. hdu_5794_A Simple Chess(lucas+dp)

    题目链接:hdu_5794_A Simple Chess 题意: 给你n,m,从(1,1)到(n,m),每次只能从左上到右下走日字路线,有k(<=100)的不能走的位置,问你有多少方案 题解: ...

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

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

  8. Codeforces Round #313 (Div. 2) E. Gerald and Giant Chess (Lucas + dp)

    题目链接:http://codeforces.com/contest/560/problem/E 给你一个n*m的网格,有k个坏点,问你从(1,1)到(n,m)不经过坏点有多少条路径. 先把这些坏点排 ...

  9. A Simple Chess (Lucas组合数 + 容斥)

    题意:走马步,要求向右向下,不能走进禁止的点.求方案数. 思路:若是n*m比较小的话,那么可以直接DP.但是这道题目不行.不过我们仔细分析可以知道从某个点到某个点是一个组合数,但是数据太大,mod值很 ...

随机推荐

  1. MYSQL数据库管理之权限管理

    经常遇到有网友在QQ群或者论坛上问关于mysql权限的问题,今天抽空总结一下关于这几年使用MYSQL的时候关于MYSQL数据库的权限管理的经验,也希望能对使用mysql的网友有所帮助! 一.MYSQL ...

  2. QCon 2015 阅读笔记 - 团队建设

    QCon 2015阅读笔记 QCon 2015 阅读笔记 - 移动开发最佳实践 QCon 2015 阅读笔记 - 团队建设 中西对话:团队管理的五项理论和实战 - 谢欣.董飞(今日头条,LinkedI ...

  3. Android 一步步教你从ActionBar迁移到ToolBar

    谷歌的材料设计也发布了有一段时间了,包括官方的support库 相信大家也熟悉了不少,今天就把actionbar 迁移到toolbar的 经验发出来. 这个地方要注意 我用的图标都是studio里的一 ...

  4. AutoCompleteTextView不能使用的问题

    AutoCompleteTextView按照网络上的方法写之后不能使用 解决方法: android:layout_width="fill_parent" 而不能是wrap_pare ...

  5. PHP开发规范

    十.开发规范下面我们讲解 Yii 编程中推荐的开发规范.为简单起见,我们假设 WebRoot 是 Yii 应用安装的目录.1.URL默认情况下,Yii 识别如下格式的 URL: http://host ...

  6. 安卓 开发 The connection to adb is down, and a severe error has occured.

    The connection to adb is down, and a severe error has occured.问题解决 其原因就是其他进程占用了  ADB的端口,所以无法启动 遇到问题描 ...

  7. 【Java多线程】互斥

    Java多线程学习2——互斥 一.前言 在上一节 (http://www.cnblogs.com/lzhen/p/3917966.html) 中,通过实现Runnable接口,可以实现多线程中的资源的 ...

  8. spring初探1

    spring初探1 关于新建对象,对象依赖的三种方式比较 场景 某个交易的业务组建拆分,为原先的功能模块新写了一个业务组件 使用new. 修改上层代码的对象生成部分( 如果不是面向接口编程,简直就是灾 ...

  9. PASCAL相关图书推荐

    PASCAL程序设计(第2版) 作      者 郑启华 著 出 版 社 清华大学出版社 出版时间 2013-01-01 版      次 2 页      数 286 印刷时间 2013-01-01 ...

  10. AI钻石天鹅风格

    第1步:描绘轮廓 你需要对你的设计有个总体的概念.利用照片和钢笔工具(P)描出轮廓.把填充颜色设为无,描边颜色设为黑色,1pt 粗细.这将作为你完成剩下设计的指导.编组 (Ctrl+G)你的线条并在图 ...