[THUPC2019]过河卒二(组合数学,容斥原理)
以后都懒得写题目大意和数据范围了。
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]过河卒二(组合数学,容斥原理)的更多相关文章
- LFYZ-OJ ID: 1020 过河卒(NOIP2002)
过河卒 Proble Description 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃 ...
- 洛谷[P1002]过河卒
原题地址:https://www.luogu.org/problemnew/show/P1002 题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点 ...
- C语言程序设计100例之(20):过河卒
例20 过河卒 题目描述 如图1,在棋盘的A点有一个过河卒,需要走到目标B点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如图1的C点),该马所在的点和所有跳跃一步可达的点称 ...
- YCOJ过河卒C++
过河卒是一道~~较简单 的问题,用递归或者动态规划都可以完成,但今天主要不是递归或者动态规划,而是用深度优先搜索做的.虽然会有两组TLE~~ 深搜是一种向下搜索的算法(如图所示) 它能有效的统计中点到 ...
- 【9307】&【a303】过河卒(NOIP2002)
Time Limit: 10 second Memory Limit: 2 MB 问题描述 如图,A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右. 同时在棋盘上的任一点有一个对方 ...
- AC日记——过河卒 洛谷 1002
题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒”. ...
- NOIP 2002过河卒 Label:dp
题目描述 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例如 ...
- ACM题目————马拦过河卒
题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒”. ...
- wikioi 1010 过河卒
题目描述 Description 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点 ...
随机推荐
- SkyWalking6.2.0版本UI参数、告警参数、指标含义中文解释
一.告警规则相关参数 二.SkyWalking UI相关参数CPM:每分钟请求调用的次数SLA: 服务等级协议(简称:SLA,全称:service level agreement).是在一定开销下为保 ...
- JSON.parse() 与 JSON.stringify()
JSON.parse() 方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象.提供可选的reviver函数用以在返回之前对所得到的对象执行变换(操作). 语法 JSON.par ...
- java 解决safari下载中文文件名乱码
主要就是在响应头设置content-disposition,主要遵循 RFC 5987标准. response.setHeader("content-disposition",&q ...
- 【题解】NOIP2015提高组 复赛
[题解]NOIP2015提高组 复赛 传送门: 神奇的幻方 \([P2615]\) 信息传递 \([P2661]\) 斗地主 \([P2668]\) 跳石头 \([P2678]\) 子串 \([P26 ...
- Queue接口分析:add和offer区别,remove和poll方法到底啥区别
Queue接口: public interface Queue<E> extends Collection<E> { /* * add方法,在不违背队列的容量限制的情况,往队列 ...
- React setState没有及时更新
1.封装 setFieldsValue 方法 /** * 更新state中的值 * data:{stateFieldName1:stateFieldvalue1...} */ setStateFiel ...
- 一款神器,批量手机号码归属地查询软件,支持导出Excel表格
很多人查询手机号码归属地,还在一个一个百度去查太慢了,如果有几万个那么是不是要百度很久 有一款软件很多人都不知道,可以吧号码复制进去,即使里面有汉字也可以把手机号码挑出来,然后查询归属地,还具有号码去 ...
- iTextSharp生成pdf含模板(二)---C#代码部分
参考地址:https://www.cnblogs.com/ibeisha/p/itextsharp-pdf.html 一.先在程序中使用Nuget安装iTextSharp(我是创建的控制台程序) 二. ...
- mask-rcnn解读(二):clip_boxes_graph()
此函数是利用deltas对box修正,我并没有详细说明,若有问题,欢迎留言交流: def clip_boxes_graph(boxes, window): """ box ...
- VirtualBox安装Ubuntu-18.04-Server笔记
准备 安装'Windows Terminal' 安装WSL 安装VirtualBox 安装 虚拟磁盘映像文件选择创建在SSD(如果有) 选择openssh,公钥从GitHub获取,前提是GitHub已 ...