$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 ;
}
随机推荐
- 16-1 djanjo介绍
一 web框架的本质 1用户的浏览器(socket客户端) 和 网站的服务器(socket服务端)之间 2 HTTP协议: 1.1 请求(request) 1.2. 响应(response) 3 we ...
- VisualStudio 自定义外部命令
通过自定义命令,可以在 VisualStudio 加上一些自定义命令,可以快速启动 git 或者做其他的事情 添加命令 首先打开工具 外部命令,点击添加,然后在弹出的窗口输入下面内容 例如添加内容是打 ...
- 字母间距letter-spacing
效果图: 字母间距CSS: h1 {letter-spacing:2px} h2 {letter-spacing:-3px}
- shell 并发执行任务
#!/bin/bash # ref: https://blog.csdn.net/spch2008/article/details/51433353 token(){ pid=$ # 判断是否有传入p ...
- oracle用>=替代>
如果DEPTNO上有一个索引, 高效: SELECT * FROM EMP WHERE DEPTNO >=4 低效: SELECT * FROM EMP WHERE DEPTNO >3 两 ...
- 只要是使用函数file_get_contents访问 https 的网站都要开启
使用file_get_contents();报错failed to open stream: Unable to find the socket transport "ssl" - ...
- get_magic_quotes_gpc() PHP转义的真正含义
如何正确的理解PHP转 义是一个初学者比较困扰的问题.我们今天为大家简要的讲述了PHP转义的具体含义,希望有所帮助.PHP转义一直困扰着我, 今天认真的看了一下PHP手册, 终于解决了. 在PHP中默 ...
- PLSQL中的三种参数模式IN、OUT、IN OUT
原文链接:https://www.cnblogs.com/zbj815/p/6854108.html 1.IN模式 IN模式是参数的默认模式,这种模式就是在程序运行的时候已经具有值,在程序体中值不会改 ...
- 2018-6-11-WPF-Frame-的-DataContext-不能被-Page-继承
title author date CreateTime categories WPF Frame 的 DataContext 不能被 Page 继承 lindexi 2018-06-11 10:48 ...
- JPA进行insert操作时会首先select吗
在某个项目中,使用JPA的saveAll方法去批量写入数据时,通过打印sql,发现每次insert前都会先select一次,极大的浪费了写入性能. 分析一下代码,saveAll() @Transact ...