HDU 5794 A Simple Chess ——(Lucas + 容斥)
网上找了很多人的博客,都看不太懂,还是大力学长的方法好。
要说明的一点是,因为是比较大的数字的组合数再加上mod比较小,因此用Lucas定理求组合数。
代码如下(有注释):
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <set>
#include <vector>
using namespace std;
const int mod = ;
typedef long long ll;
typedef pair<ll,ll> pii; int k;
ll fact[+],dp[+];
ll n,m;
vector<pii> V; void init()
{
fact[] = fact[] = ;
for(int i=;i<=;i++) fact[i] = fact[i-] * i % mod;
} void ex_gcd(ll a,ll b,ll &x,ll &y,ll &d)
{
if(!b) {d = a; x = ; y = ;}
else
{
ex_gcd(b,a%b,y,x,d);
y -= x * (a/b);
}
} ll qpow(ll a,ll b)
{
ll ans = ;
while(b)
{
if(b & ) ans = ans * a % mod;
a = a * a % mod;
b >>= ;
}
return ans;
} ll inv(ll t,ll p)
{
/*ll x,y,d;
ex_gcd(t,p,x,y,d);
return d==1 ? (x%mod+mod)%mod : -1;*/
return qpow(t,p-);
} int comb(int n,int m)
{
if(m< || n<m) return ;
return fact[n] * 1LL * inv(fact[m],mod) % mod * inv(fact[n-m],mod) % mod;
} ll Lucas(ll n,ll m,int p)
{
return m ? Lucas(n/p,m/p,p) * comb(n%p,m%p) % mod : ;
} ll solve(int i,int j) // j to i 的无视障碍的步数总数
{
if(V[i].second < V[j].second || V[i].first < V[i].first || (V[i].first+V[i].second-V[j].first-V[j].second)%) return -;
ll need = (V[i].first+V[i].second-V[j].first-V[j].second) / ;
// need 表示走过的步数
ll step = Lucas(need, V[i].first-V[j].first-need, mod);
// 第二个参数表示走过的两步的步数
// 总的步数(need)中选择若干步是走两步的
return step % mod;
} int main()
{
init();
int kase = ;
while(scanf("%I64d%I64d%d",&n,&m,&k)==)
{
V.clear();
for(int i=;i<=k;i++)
{
ll x,y;scanf("%I64d%I64d",&x,&y);
V.push_back(pii(x,y));
}
V.push_back(pii(,));
V.push_back(pii(n,m));
sort(V.begin(),V.end());
memset(dp,,sizeof(dp));
int sz = V.size();
for(int i=;i<sz;i++)
{
dp[i] = solve(i,);
if(dp[i] == -) dp[i] = ;
for(int j=;j<i;j++)
{
ll step = solve(i,j);
if(step != -)
{
dp[i] -= step * dp[j] % mod;
// 所有从原点到i这个点的路径中,从原点到禁止点再从该禁止点到i点的所有路径都是不被允许的,需要减掉
if(dp[i] < ) dp[i] = ((dp[i] % mod) + mod) % mod;
}
}
}
printf("Case #%d: %I64d\n",kase++,dp[sz-]);
}
}
HDU 5794 A Simple Chess ——(Lucas + 容斥)的更多相关文章
- 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 + 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
HDU 5794 - A Simple Chess题意: 马(象棋)初始位置在(1,1), 现在要走到(n,m), 问有几种走法 棋盘上有r个障碍物, 该位置不能走, 并规定只能走右下方 数据范围: ...
- 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(杨辉三角+容斥原理+Lucas定理)
题目链接 A Simple Chess 打表发现这其实是一个杨辉三角…… 然后发现很多格子上方案数都是0 对于那写可能可以到达的点(先不考虑障碍点),我们先叫做有效的点 对于那些障碍,如果不在有效点上 ...
- hdu 5792(树状数组,容斥) World is Exploding
hdu 5792 要找的无非就是一个上升的仅有两个的序列和一个下降的仅有两个的序列,按照容斥的思想,肯定就是所有的上升的乘以所有的下降的,然后再减去重复的情况. 先用树状数组求出lx[i](在第 i ...
- hdu_5794_A Simple Chess(lucas+dp)
题目链接:hdu_5794_A Simple Chess 题意: 给你n,m,从(1,1)到(n,m),每次只能从左上到右下走日字路线,有k(<=100)的不能走的位置,问你有多少方案 题解: ...
- HDU 1695 GCD 欧拉函数+容斥定理 || 莫比乌斯反演
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
随机推荐
- mybatis数组和集合的长度判断及插入
1.在使用foreach的是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下4种情况: 如果传入的是单参数且参数类型是一个List的时候,collect ...
- c#连接Java后台,处理返回的数据
首先定义共通文件,根据url连接Java后台 class ConntectUtil { public JObject ConsoleApplication(string appID, CustomDa ...
- Linux工具- Sysdig
Sysdig 是一个超级系统工具,比 strace.tcpdump.lsof 加起来还强大.可用来捕获系统状态信息,保存数据并进行过滤和分析.使用 Lua 开发,提供命令行接口以及强大的交互界面. 使 ...
- maven入门-- part3 生命周期
简介: Maven有三套相互独立的生命周期,请注意这里说的是“三套”,而且“相互独立”,这三套生命周期分别是: Clean Lifecycle 在进行真正的构建之前进行一些清理工作. Default ...
- linux递归查找目录下所有文件夹以及文件
相对于ls或者ll,可能find在这个时候更加给力 先看我的目录结构 tree命令是查看目录的结构,而且最后会列出所有的directory的数目以及文件夹的数目...好像我们接下来要做的就没有必要了, ...
- mybatis sql语句中 in() 长度为0或null的情况
mybatis sql语句中 in() 长度为0或null的情况 比如: select * from A where colName IN <foreach collection="m ...
- php--常见算法2
<?php function zhi($number){ $f1=1; $f2=1; for($i=3;$i<=$number;$i++){ //前一个的前一个值+前一个值 $f3=$f1 ...
- Python学习记录1-基础知识
基础知识 基础 #简单记录了部分基础知识 #普通的打印字符串 >>> print("hello world") hello world ------------- ...
- arm交叉编译sudo-1.8.6p7
1.交叉编译 # tar -xvf sudo-1.8.6p7.tar.gz # cd sudo-1.8.6p7/ # mkdir build # ./configure --prefix=/home/ ...
- 6.JVM技术_java内存模型
1.java内存模型图解 Java虚拟机在执行Java程序的过程中,会把它所管理的内存划分为若干个不同的数据区.这些区域有各自的用途,以及创建和销毁的 时间,有的区域随着虚拟机进程的启动而存在,有的区 ...