HDU 5794 - A Simple Chess
HDU 5794 - A Simple Chess
题意:
马(象棋)初始位置在(1,1), 现在要走到(n,m), 问有几种走法
棋盘上有r个障碍物, 该位置不能走, 并规定只能走右下方
数据范围: ( 1 ≤ n,m ≤10^18, 0 ≤ r ≤100 )
分析:
分析不存在障碍物时的走法规律:
(1,1) 1
(2,3) (3,2) 1 1
(3,5) (4,4) (5,3) 1 2 1
(4,7) (5,6) (6,5) (7,4) 1 3 3 1
...... ......
发现走法规律是一个斜着的杨辉三角, 即i层第j个的走法数为: C[i,j-1] (组合数)
那么根据换算, 层数 = (x+y+1)/3 - 1 , 个数 = x - (x+y+1)/3
即可得到无障碍物时,(m,n)点的路径数
分析障碍物的贡献与障碍物之间的相互影响:
障碍物(x,y)的贡献 = (1,1)到(x,y)的路径数 * (x,y)到(n,m)的路径数, 后者通过相对位置(平移)计算
障碍物之间的影响, 即应去掉的重复部分, 也如此计算
因为n,m数据范围大, 故计算组合数应用 LUCAS定理
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
const LL MOD = ;
long long fac[MOD];
//求a^n % MOD的值
template<class T1, class T2>
T1 QuickPow(T1 x, T2 n, T1 MOD)
{
T1 ans = ;
while (n)
{
if (n & ) ans = (ans * x) % MOD;
x = (x * x) % MOD;
n >>= ;
}
return ans;
}
//组合数
//参数为C(n, m) % p (p为质数)
//fac[i]表示i! % p
template<class T, class Type>
T C(Type n, Type m, T p)
{
if (n < m) return ;
T x = fac[n], y = fac[n-m] * fac[m] % p;
return x * QuickPow(y, p - , p) % p;
}
//生成i! % p (i = 0->p-1)
//配合Lucas定理使用
template<class T>
void ProFac(T *fac, T p)
{
fac[] = ;
for (int i = ; i < (int)p; i++)
fac[i] = fac[i-] * i % p;
}
//Lucas定理
//求C(n, m) % p (n, m可以很大, p最大可为1e5, p为质数)
//后面两个参数内部使用,不必考虑
template<class T>
T Lucas(T n, T m, T p)
{
if (m == ) return 1LL;
else
{
T res = C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
return res;
}
} inline bool change(LL x,LL y, LL &m,LL &n) //将(x,y) 转为 C[b][a]
{
if((x + y + ) % != ) return ;
LL a = (x + y + ) / ;
if(x < a || y < a) return ;
m = x - a;
n = a - ;
return ;
} struct CC
{
LL x, y, a, b;
}g[];
LL n, m, a, b;
int r, tot;
LL gx[], gy[], val[];
LL ans; bool cmp(CC a, CC b)
{
return a.b < b.b;
}
bool flag;
int main()
{
ProFac(fac, MOD);
int tt = ;
while (~scanf("%lld%lld%d",&n,&m,&r))
{
flag = ;
for (int i = ; i <= r; i++)
{
scanf("%lld%lld", &gx[i], &gy[i]);
if(gx[i] == n && gy[i] == m) flag = ;
}
printf("Case #%d: ", tt++);
if (flag || !change(n, m, a, b)) //障碍物在 n,m 点,或者不能跳到n,m
{
puts(""); continue;
}
tot = ;
for (int i = ; i <= r; i++)
{
if (!change(n - gx[i] + ,m - gy[i] + , g[tot].a, g[tot].b)) continue; //该位置不能影响到 n,m点
if (change(gx[i], gy[i], g[tot].a, g[tot].b)) // 有效障碍物点
{
g[tot].x = gx[i], g[tot].y = gy[i];
tot++;
}
}
ans = Lucas(b, a, MOD);//C[b][a]
sort(g, g + tot, cmp);
for (int i = ; i < tot; i++)
{
val[i] = Lucas(g[i].b, g[i].a, MOD);//到每个障碍物的的路径数
}
for (int i = ; i < tot; i++)
{
LL a1, b1, tmp;
if (!change(n - g[i].x + , m - g[i].y + , a1, b1) ) continue;
tmp = Lucas(b1, a1, MOD);
ans = (ans + MOD - (val[i] * tmp % MOD )) % MOD;//减去障碍物贡献
for (int j = i + ; j < tot; j++)
{
if ( !change(g[j].x - g[i].x + , g[j].y - g[i].y + , a1, b1) ) continue;
tmp = Lucas(b1, a1, MOD);
val[j] = (val[j] + MOD - (val[i] * tmp % MOD )) % MOD; //减去障碍物之间的影响
}
}
printf("%lld\n", ans);
}
}
HDU 5794 - A Simple Chess的更多相关文章
- 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 (容斥+DP+Lucas)
A Simple Chess 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5794 Description There is a n×m board ...
- HDU 5794 A Simple Chess(杨辉三角+容斥原理+Lucas定理)
题目链接 A Simple Chess 打表发现这其实是一个杨辉三角…… 然后发现很多格子上方案数都是0 对于那写可能可以到达的点(先不考虑障碍点),我们先叫做有效的点 对于那些障碍,如果不在有效点上 ...
- 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的网格.网格上有一些点是障碍,不能经过.行走的方式是向右下角跳马步.求 ...
- HDU 5794 A Simple Chess ——(Lucas + 容斥)
网上找了很多人的博客,都看不太懂,还是大力学长的方法好. 要说明的一点是,因为是比较大的数字的组合数再加上mod比较小,因此用Lucas定理求组合数. 代码如下(有注释): #include < ...
- HDU 5794 - A Simple Nim
题意: n堆石子,先拿光就赢,操作分为两种: 1.任意一堆中拿走任意颗石子 2.将任意一堆分成三小堆 ( 每堆至少一颗 ) 分析: 答案为每一堆的 ...
- 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 ...
- 2016暑假多校联合---A Simple Chess
2016暑假多校联合---A Simple Chess Problem Description There is a n×m board, a chess want to go to the po ...
随机推荐
- Winform中子线程访问界面控件时被阻塞解决方案
public partial class WebData_Import : Form { //声明用于访问主界面的委托类型 public delegate void deleGetOrderdata( ...
- nginx+tomcat的集群和session复制
前端服务器采用nginx,后端应用服务器采用tomcat.nginx负责负载均衡,session复制在tomcat上处理. 1.nginx安装(略) 2.nginx配置负载均衡 http { incl ...
- 新浪授权认证(不用SDK)
微博开放平台:http://open.weibo.com/ 微博开放接口的调用,如发微博.关注等,都是需要获取用户身份认证的.目前微博开放平台用户身份鉴权主要采用的是OAuth2.0.另外,为了方便开 ...
- Niagara AX之BajaScript资料哪里找
四个步骤:(开篇:多谢陈工!) 1.Services下添加box->boxService: 2.在Apps下添加BajaScriptTutorialsApp: 3.登录用户的Web Profil ...
- 【python学习笔记01】python的数据类型
python的基本数据类型 整型 int 浮点型 float 真值 bool 字符串 str 列表 list #[1,2,3] 元组 tuple #(1,2,3) 字典 dict ...
- ubuntu安装配置gradle
在Ubuntu安装Gradle也是很简单.切记请勿使用apt-get安装Gradle.因为Ubuntu源的Gradle实在太旧.安装好基本不能用. 下面是安装步骤: 1.在官网下载最新的Gradle版 ...
- [转] Lisp语言:Do循环的使用
转自http://blog.csdn.net/keyboardota/article/details/8240250 有关Lisp语言中的Do循环,就像很多人说的一样,初看起来太奇怪了,不知道怎么理解 ...
- Histats申请Counter网站计数器 - Blog透视镜
为了计算网页被浏览的次数,访客人数等统计数据,作为未来分析之用,可以向Histats申请免费的Counter网站计数器,它的功能相当齐全,同时也会保留一段时间的资料,当作统计比较的资料,更可以进一步付 ...
- LeetCode_Jump Game II
Given an array of non-negative integers, you are initially positioned at the first index of the arra ...
- CSS之Hack
一.类内部Hack IE都能识别*;标准浏览器(如FF)不能识别*:IE6能识别*,但不能识别 !important, IE7能识别*,也能识别!important; FF不能识别*,但能识别!imp ...