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


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. | C语言I作业12

    C语言I作业12-学期总结 标签:18软件 李煦亮 问题 答案 这个作业属于那个课程 C语言程序设计I 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/S ...

  2. 阿里云ECS服务器CentOS7.2安装Python2.7.13

    阿里云ECS服务器CentOS7.2安装Python2.7.13 yum中最新的也是Python 2.6.6,只能下载Python 2.7.9的源代码自己编译安装. 操作步骤如下: 检查CentOS7 ...

  3. Hbase put写入源码分析

    今天有空闲时间看一下HBASE的写入代码 MutiAction类,是一个action的container,包括get . put. delete.并且是根据region name分组的.其中核心的就是 ...

  4. Nginx 极简入门教程!

    上篇文章和大家聊了 Spring Session 实现 Session 共享的问题,有的小伙伴看了后表示对 Nginx 还是很懵,因此有了这篇文章,算是一个 Nginx 扫盲入门吧! 基本介绍 Ngi ...

  5. 4-5 Scrapy知识补充

    FormRequest FormRequest类是专门用来处理HTML表单的,同时对隐藏的表单处理也很方便.适合用来完成登录操作. 类原型:class scrapy.http.FormRequest( ...

  6. 硬件笔记之制作MacOS Mojave U盘USB启动安装盘方法

    0x00 概述 随着苹果 macOS Mojave 正式版发布,很多使用 Mac 电脑的同学都已升级到最新版了.但如果你对系统有洁癖或原本系统已凌乱不堪,那么可能还是希望能格式化「全新安装 macOS ...

  7. vue中操作localstorage

    首先在子组件将localstorage方法进行封装 在父组件中对其进行引用 将输入的值存入到定义的searchHistory数组中,存储localstorage需要传两个参数,变量名为searchHi ...

  8. Asp.net MVC企业级开发(02)---Log4net

    Log4Net 是用来记录日志的,可以将程序运行过程中的信息输出到一些地方(文件.数据库.EventLog等).日志就是程序的“黑匣子”,可以通过日志查看系统的运行过程,从而发现系统的问题. 日志的作 ...

  9. Python中的@函数装饰器到底是什么?

    在解释@函数装饰器之前,先说一下,类中的类方法和静态方法. 在Python中完全支持定义类方法.静态方法.这两种方法很相似,Python它们都使用类来调用(ps:用对象调用也可以). 区别在于:Pyt ...

  10. python 库 PrettyTabble 使用与错误

    参考链接:http://zetcode.com/python/prettytable/ PrettyTable能在python中生成ASCII 表,可以使用他控制表的很多方面,包括文本对齐.表的边框. ...