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 ...
随机推荐
- 配置IIS
1.aspnet_regiis -i 重新安装IIs vs2013的命令符 2. 分配权限 1.对文件夹,权限,安全,分配权限 2.设置webconfig 对应的httpModel 及安全性 3.设 ...
- SQL Server中带事务的存储过程简单举例
先来看一个概念: 数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完整地执行,要么完全地不执行.那么在存储过程里添加事务,则可以保证该事务里的所 ...
- python连接postgresql数据库
python可以通过第三方模块连接postgresql. 比较有名的有psycopg2 和python3-postgresql (一)psycopg2 ubuntu下安装 sudo apt-get ...
- javascript获取页面文档内容
<html> <head> <title>JavaScript基础</title> </head> <body> <p&g ...
- javascript跨域获取json数据
项目在开发过程中,用到了天气预报的功能,所以需要调用天气预报的api,一开始以为直接用ajax调用url就可以获取天气数据,结果涉及到了跨域的问题,这里做一个记录. 说到跨域,就得知道同源策略. 同源 ...
- sql helper
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.C ...
- Mysql基本类型(五种年日期时间类型)——mysql之二
转自:<MySQL技术内幕:时间和日期数据类型> http://tech.it168.com/a2012/0904/1393/000001393605_all.shtml
- 对Qt for Android的评价(很全面,基本已经没有问题了,网易战网客户端就是Qt quick写的),可以重用QT积累20年的RTL是好事,QML效率是HTML5的5倍
现在Qt不要光看跨平台了,Qt也有能力和原生应用进行较量的.可以直接去Qt官网查看他和那些厂商合作.关于和Java的比较,框架和Java进行比较似乎不且实际.如果是C++和Java比较,网上有很多文章 ...
- ViewBag、ViewData和TempData使用方法、区别与联系
一.区别与联系 ViewData 和 TempData 都可以传递弱类型数据,区别如下:TempData 只在当前 Action 中有效,生命周期和 View 相同:保存在Session中,Contr ...
- Http响应报文
HTTP响应也由三个部分组成,分别是:状态行.消息报头.响应正文. 其中,HTTP-Version表示服务器HTTP协议的版本:Status-Code表示服务器发回的响应状态代码:Reason-Phr ...