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 ...
随机推荐
- 你所不了解的css选择器补充
div p和div>p的区别 1.div p选择 <div> 元素内部的所有 <p> 元素 2.div>p选择父元素为 <div> 元素的所有 < ...
- OpenCV——使用ROI进行图像切割
ROI(region of interest)——感兴趣区域. 1.用途 这个区域是图像分析所关注的重点.圈定这个区域,以便进行进一步的处理.而且,使用ROI指定 想读入的目标,可以减少处理时间,增加 ...
- (转)Ubuntu中使用dpkg安装deb文件提示依赖关系问题,仍未被配置
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5638149.html 参考网址: http://zhidao.baidu.com/link?url=b ...
- JavaScript当中的eval函数
eval函数 eval函数接收一个由JavaScript语句组成的字符串,并且返回字符串中最后一条语句的返回值,如果最后一条语句没有返回值,那么eval函数返回undefined.如果传递给eval函 ...
- YUI Array 之hash
hash就是把两个参数合并成一个类似hashMap结构的对象,用第一个数组的元素为key,第二个的为value,如果第二个参数未指定,则把对象的对应的值置为true YUI原码 YUI hashYAr ...
- mysql函数全解析
本文摘自:http://www.cnblogs.com/cocos/archive/2011/05/06/2039469.html mysql函数大全 对于针对字符串位置的操作,第一个位置被标记为1. ...
- Hibernate中HQL的日期差值计算,可计算相差多少秒
最近有个业务需求就是计算订单创建时间离现在超过 4 小时的订单都查找出来! 那么就需要用到日期函数了. 网上找了一下总共的日期函数有一下几个: CURRENT_DATE() 返回数据库当前日期 时间函 ...
- 记录一下C#+Oracle批量插入的一个方法
public bool insertOracle(DataTable dataTable, string sql) // Oracle sql 查询的是表头 { string ConnStr = Wi ...
- vs2003的代码考到vs2010 会出现(Windows CR LF)
拷贝到VS中,出现各种莫名其妙的编译错误,这个时候需要注意,造成这种情况的原因可能在于,你所拷贝的源代码在换行时并非采用Windows系统的CR LF方式. 下面给出一个简单的方法来将不合要求的文本更 ...
- NicEdit - WYSIWYG Content Editor, Inline Rich Text Application
NicEdit - WYSIWYG Content Editor, Inline Rich Text Application By calling the nicEditors.allTextarea ...