$CF559C\ Gerald\ and\ Fiant\ Chess$ 计数类$DP$
Description
有个$H$行$W$列的棋盘,里面有$N$个黑色格子,求一个棋子由左上方格子走到右下方格子且不经过黑色格子的方案数.
$1<=H,M<=1e5,1<=N<=2000$.输出对$1e9+7$去模后的结果即可
Sol
假设没有黑色格子,方案数就为$C_{H+W-2}^{H-1}$.
简单说下,可以把向下走看做$0$,向右走看做$1$,其实就是求$01$序列的种数
注意到,黑色格子的总数相当少,所以我们可以把求不经过黑色格子的方案数转化成总方案数减去至少经过一个黑色格子的方案数
在求解计数类$DP$问题时,通常要找到一个"基准点",围绕这个基准点构造一个不可划分的"整体",以避免子问题的重叠.
这句话的意思大概就是找到标准把问题划分为子问题,且这些子问题具有互斥性.
将统计至少经过一个黑色格子的问题转化为枚举每一个黑色格子,并且将以该黑色格子为第一个经过的黑色格子的路径方案数相加.(定语似乎太长了,但是应该都懂的叭)
具体来说,将所有的黑色格子按照行,列坐标递增的顺序排序.第$i$个黑色格子在第$xi$行,$yi$列,设$F[i]$表示从左上角走到第$i$个黑色格子,并且途中不经过其他黑色格子的路线数.
$F[i]=C_{xi-1+yi-1}^{xi-1}-\sum_{j=0}^{i-1}F[j]*C_{xi-xj+yi-yj}^{xi-xj}$,其中$xi>=xj,yi>=yj$
特别地,我们假设左上角的格子为第$0$个黑色格子,右下角的格子为第$N+1$个黑色格子.以$F[0]=1$为初值,$F[n+1]$为答案.
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#define il inline
#define Rg register
#define go(i,a,b) for(Rg int i=a;i<=b;i++)
#define yes(i,a,b) for(Rg int i=a;i>=b;i++)
#define ll long long
using namespace std;
il int read()
{
int x=,y=;char c=getchar();
while(c<''||c>''){if(c=='-')y=-;c=getchar();}
while(c>=''&&c<=''){x=(x<<)+(x<<)+c-'';c=getchar();}
return x*y;
}
const int N=,M=;
int h,w,n,mod=(1e9)+;
ll f[N],jc[M],inv[M];
struct node{int x,y,s;}a[N];
il bool cmp(node x,node y){if(x.x==y.x)return x.y<y.y;return x.x<y.x;}
il ll ksm(ll x,int y)
{
ll s=;
while(y){if(y&)s=(s*x)%mod;x=(x*x)%mod;y>>=;}
return s;
}
il void init_C()
{
jc[]=,inv[]=;
go(i,,)
jc[i]=jc[i-]*i%mod,inv[i]=ksm(jc[i],mod-);
}
il ll C(int x,int y)
{
return jc[x]*inv[y]%mod*inv[x-y]%mod;
}
int main()
{
h=read(),w=read(),n=read();init_C();
go(i,,n){a[i]=(node){read(),read()},a[i].s=a[i].x+a[i].y;}
a[n+]=(node){h,w,h+w};
sort(a+,a+n+,cmp);
go(i,,n+)
{
f[i]=C(a[i].s-,a[i].x-);
go(j,,i-)
{
if(a[j].x>a[i].x || a[j].y>a[i].y)continue;
f[i]=(f[i]-f[j]*C(a[i].s-a[j].s,a[i].x-a[j].x))%mod;
}
}
printf("%lld\n",(f[n+]+mod)%mod);
return ;
}
随机推荐
- 原生JS使用Blob导出csv文件
最近在做关于文件下载的需求:前端调用接口,然后对返回数据进行过滤.格式化,然后按表格内容拼接生成csv文件,让用户下载. 具体实现方式如下:let sourceData = { head: [ '时间 ...
- 5-2 正则表达式及其re模块
一 正则表达式 在线测试工具 http://tool.chinaz.com/regex/ 字符 量词 贪婪匹配 贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配,<.*&g ...
- @bzoj - 4377@ [POI2015] Kurs szybkiego czytania
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定 n, a, b, p,其中 n, a 互质.定义一个长度为 ...
- uni-app禁止滑动穿透
<view class="topWrapper" v-show="chooseShow" @click="chooseShow = false& ...
- Android Xutils框架使用问题及解决办法
刚刚写了篇博客,提了下在使用XUtils时遇到的一个问题Android Xutils框架HttpUtil Get请求缓存问题 ,既然已经提起来这个问题,那我想了下,就把之前使用Xutils时遇到的几个 ...
- hdu 1535 Invitation Cards(spfa)
Invitation Cards Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ...
- [转载] CentOS系统开机自动挂载光驱 和 fstab文件详解
参考 http://blog.itpub.net/12272958/viewspace-676977/ 一.开机自动挂载光驱 1.按习惯,root用户,在/media目录下建立目录cdrom——mkd ...
- C++调用Lua编程环境搭建及测试代码示例
C++调用Lua编程环境搭建及测试代码示例 摘要:测试环境是VS2005+LuaForWindows_v5.1.4-45.exe+WIN7 1.安装lua开发环境LuaForWindows_v5.1. ...
- [转]Springboot和SpringMVC区别
spring boot只是一个配置工具,整合工具,辅助工具. springmvc是框架,项目中实际运行的代码 Spring 框架就像一个家族,有众多衍生产品例如 boot.security.jpa等等 ...
- Spring boot+JPA+Druid
pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...