$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 ;
}
随机推荐
- Xcode4.2 本地化 总结
1 xcode4.2,如果是简体中文,把国际化的文件放到zh-Hans.lproj中就显示正常了.如果放到zh.lproj中就不可以 2 字符串 1)在项目的"supporting file ...
- Facebook F8|闲鱼高级技术专家参会分享
笔者代表闲鱼参加了Facebook在4月30日举行的为期二天的F8大会,地点加州.将会议概括和一些收获分享给大家.对国内开发者而言,Facebook的产品设计.社区.VR/AR等有一些借鉴意义:对海外 ...
- @codechef - RNG@ Random Number Generator
目录 @description@ @solution@ @part - 1@ @part - 2@ @part - 3@ @accepted code@ @details@ @description@ ...
- saltStack_Pillar
Pillar是Salt非常重要的一个组件,它用于给特定的minion定义任何你需要的数据,这些数据可以被Salt的其他组件使用.这里可以看出Pillar的一个特点,Pillar数据是与特定minion ...
- ODT模板
struct node{ int l,r; mutable int v; node(int L,int R,int V):l(L),r(R),v(V){} inline bool operator & ...
- LRJ-Example-06-01-Uva210
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstdlib> #include <cstrin ...
- jq实现超级简单的隔行变色
文章地址:https://www.cnblogs.com/sandraryan/ <!DOCTYPE html> <html lang="en"> < ...
- setTimeout与setInterval有何区别?
①setTimeout和setInterval的语法相同.它们都有两个参数,一个是将要执行的代码字符串,还有一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将执行那段代码. ②不过这两个函数还是有 ...
- Vue之webpack的安装与配置及其简单应用
一.文件结构 二.index.html <!DOCTYPE html> <html lang="en"> <head> <meta cha ...
- visualStudio 无法登陆
如果遇到 visualStudio 无法登陆,可以看下我的方法,可能有用 尝试关闭代理 打开设置.网络.代理,关了它,试试 如果遇到下面的问题: 我们无法刷新此账户的凭据 No home tenant ...