以后都懒得写题目大意和数据范围了。


hz学长的题其实也不那么毒瘤吗。比CDW的好多了

先考虑没有障碍怎么做。

首先发现,答案相当于一个左下角是 $(1,1)$,右上角是 $(n+1,m+1)$ 的棋盘,从 $(1,1)$ 走到 $(n+1,m+1)$ 的方案数。因为走到最上或最右就只有一种选法了。

枚举斜着走的次数 $i$。答案是 $\sum\limits_{i=0}^{\min(n,m)}\dbinom{n+m-i}{i}\dbinom{n+m-2i}{n-i}$。前面是选哪几步,后面是经典过河卒。(注意 $n,m$ 是 $x2-x1$ 和 $y2-y1$)

现在考虑有障碍。明显容斥。

令 $g[S]$ 表示至少经过 $S$ 中障碍的方案数。(可能经过更多的障碍)

答案是 $\sum\limits_Sg[S](-1)^{|S|}$。

如何计算 $g[S]$?

先把障碍按 $x$ 为第一关键字排序,按 $y$ 为第二关键字排序。

那么 $S$ 中如果存在 $i<j,y[i]>y[j]$ 那么为 $0$。

否则就是从起点到第一个点的方案数,从第一个点到第二个点的方案数……从最后一个点到终点的方案数的乘积。

时间复杂度看起来是 $O(2^k\min(n,m))$。

但是我们发现很多个方案数是被重复计算的。如果我们预处理两两点之间的方案数就能做到 $O(2^kk+k^2\min(n,m))$。

模数是质数,可以用卢卡斯定理。

#include<bits/stdc++.h>
using namespace std;
const int mod=;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
struct pos{
int x,y;
bool operator<(const pos &p)const{
if(x!=p.x) return x<p.x;
return y<p.y;
}
}p[];
int n,m,k,x[],y[],cnt[][],fac[mod],inv[mod],invfac[mod],ans,sz[],in[],out[];
void init(){
fac[]=fac[]=inv[]=invfac[]=invfac[]=;
FOR(i,,mod-){
fac[i]=1ll*fac[i-]*i%mod;
inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod;
invfac[i]=1ll*invfac[i-]*inv[i]%mod;
}
}
int C(int n,int m){
if(n< || m< || n<m) return ;
return 1ll*fac[n]*invfac[m]%mod*invfac[n-m]%mod;
}
int lucas(int n,int m){
if(n<mod) return C(n,m);
return 1ll*lucas(n/mod,m/mod)*lucas(n%mod,m%mod)%mod;
}
int calc(int n,int m){
int ans=;
FOR(i,,min(n,m)) ans=(ans+1ll*lucas(n+m-i,i)*lucas(n+m-*i,n-i))%mod;
return ans;
}
int solve(int S){
int pre=-,ans=;
FOR(i,,k-) if((S>>i)&){
if(pre==-) ans=1ll*ans*in[i]%mod;
else{
if(y[pre]>y[i]) return ;
ans=1ll*ans*cnt[pre][i]%mod;
}
pre=i;
}
if(~pre) return 1ll*ans*out[pre]%mod;
else return calc(n,m);
}
int main(){
n=read();m=read();k=read();
init();
FOR(i,,k-) p[i].x=read(),p[i].y=read();
sort(p,p+k);
FOR(i,,k-) x[i]=p[i].x,y[i]=p[i].y;
FOR(i,,k-) FOR(j,i+,k-) cnt[i][j]=calc(x[j]-x[i],y[j]-y[i]);
FOR(i,,k-) in[i]=calc(x[i]-,y[i]-),out[i]=calc(n+-x[i],m+-y[i]);
FOR(i,,(<<k)-) sz[i]=sz[i>>]+(i&);
FOR(i,,(<<k)-){
if(sz[i]&) ans=(ans-solve(i)+mod)%mod;
else ans=(ans+solve(i))%mod;
}
printf("%d\n",ans);
}

[THUPC2019]过河卒二(组合数学,容斥原理)的更多相关文章

  1. LFYZ-OJ ID: 1020 过河卒(NOIP2002)

    过河卒 Proble Description 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃 ...

  2. 洛谷[P1002]过河卒

    原题地址:https://www.luogu.org/problemnew/show/P1002 题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点 ...

  3. C语言程序设计100例之(20):过河卒

    例20  过河卒 题目描述 如图1,在棋盘的A点有一个过河卒,需要走到目标B点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如图1的C点),该马所在的点和所有跳跃一步可达的点称 ...

  4. YCOJ过河卒C++

    过河卒是一道~~较简单 的问题,用递归或者动态规划都可以完成,但今天主要不是递归或者动态规划,而是用深度优先搜索做的.虽然会有两组TLE~~ 深搜是一种向下搜索的算法(如图所示) 它能有效的统计中点到 ...

  5. 【9307】&【a303】过河卒(NOIP2002)

    Time Limit: 10 second Memory Limit: 2 MB 问题描述 如图,A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右. 同时在棋盘上的任一点有一个对方 ...

  6. AC日记——过河卒 洛谷 1002

    题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒”. ...

  7. NOIP 2002过河卒 Label:dp

    题目描述 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例如 ...

  8. ACM题目————马拦过河卒

    题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒”. ...

  9. wikioi 1010 过河卒

    题目描述 Description 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点 ...

随机推荐

  1. Neo4j图数据库从入门到精通(转)

    add by zhj: 转载时,目录没整理好,还会跳转到原文 其实RDB也可以存储多对多的关系,使用的是中间表,GDB使用的是边,RDB中的实体存储在数据表,而GDB存储在节点.两者使用的底层技术不同 ...

  2. 【生活现场】从打牌到map-reduce工作原理解析(转)

    原文:http://www.sohu.com/a/287135829_818692 小史是一个非科班的程序员,虽然学的是电子专业,但是通过自己的努力成功通过了面试,现在要开始迎接新生活了. 对小史面试 ...

  3. 《 .NET并发编程实战》阅读指南 - 第1章

    先发表生成URL以印在书里面.等书籍正式出版销售后会公开内容.

  4. excel中统计列中的值在其他列出现的次数多个条件

    excel中统计列中的值在其他列出现的次数多个条件 =COUNTIFS(E2:E373,"=VIP经销商",J2:J373,K2) 解释 E列的第二行到第373行中值 等于 VIP ...

  5. 七雄Q传封包辅助技术探讨回忆贴

    前言 网页游戏2013年左右最火的类型最烧钱游戏,当年的我也掉坑了.为了边玩还满足码农精神我奋力的学习如何来做外挂.2013年我工作的第二个年头.多一半…介绍下游戏<七雄Q传>是北京游戏谷 ...

  6. SQL 增、删、改、查语句

    1.SQL SELECT 语句 SELECT语句用于从表中选取数据. 结果被存储在一个结果表中(称为结果集). SQL SELECT语法 SELECT 列名称 FROM 表名称 以及 SELECT * ...

  7. 在 VSCode 调试过程中,使用 Watcher,免手动重新编译

    1.安装Microsoft.DotNet.Watcher.Tools包 dotnet add package Microsoft.DotNet.Watcher.Tools --version 2.0. ...

  8. MVC下通过jquery的ajax调用webapi

    如题 jquery的应用,不会的自己去补. 创建一个mvc项目,新建控制器.视图如下: 其中data控制器负责向前台提供数据,home控制器是一个简单的访问页控制器. data控制器代码如下: pub ...

  9. 【JZOJ】2126. 最大约数和

    题目大意 选取和不超过S的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大. 分析 把我们分解出来的因数进行合并,存在一个不知名的数组里,然后我们大可开始我们的迪屁!!(bag),我们可以 ...

  10. vi/vim的快捷操作(2)

    1.拷贝当前行[yy],拷贝当前行向下的5行[5yy],并粘贴[p] 2.删除当前行[dd],删除当前行向下的5行[5dd] 3.在文件中查找某个单词,命令行模式下输入[/关键字],回车查找,输入[n ...