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


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. HUT 排序训练赛 F - 水果

    Problem's Link Mean: 略. analyse: 使用结构体排序. 首先,定义一个结构体,用来存放输入的数据,然后就是输入,注意:这儿有一个小细节,输入数字,然后紧跟着输入字符串,这时 ...

  2. SFTP 定时任务下载

    1.上传 winscp.exe /console /command "option batch continue" "option confirm off" & ...

  3. C++ 中 string和char* 的区别

    C++ 中 string和char* 的区别 1.定义: string:string是STL当中的一个容器,对其进行了封装,所以操作起来非常方便. char*:char *是一个指针,可以指向一个字符 ...

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

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

  5. ASP.NET Core 中的 Razor 文件编译

    asp .net core mvc 3.0 在编译的时候做了一些改变,有些view视图更改需要重新编译,你也可以配置运行时编译,不用每次更改都去重新生成,具体代码如下,从官方文档看到,做个记录. Ra ...

  6. python 中问题,包括某些库的问题

    *)TypeError: exceptions must derive from BaseException 原因是raise语句没有写好 raise('value must between 0 an ...

  7. golang-Json编码解码

    目录 一. 类型映射 二. 输出控制 三. 类型编码 四. 类型解码 五. 输出重写 六. 扩展功能 七. Bson编码 在线工具:https://www.json.cn 一. 类型映射 golang ...

  8. 很全的vue插件汇总,赶紧收藏下(转)

    Vue是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件特别整理了常用的vue插件,来了个大汇总,方便查找使用,便于工作 ...

  9. ES6兼容ie9, flex兼容ie9

    vue兼容ES6 在 ie9 的环境上,es6 的部分新对象.表达式,并不支持,解决方案是使用 babel-polyfill 组件,它可以将 es6 的代码翻译成低版本浏览器可以识别的 es5 代码 ...

  10. awit的用法,等待执行结果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...