加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

$CF559C\ Gerald\ and\ Fiant\

发布时间:2020-12-16 10:48:53 所属栏目:百科 来源:网络整理
导读:AcWing ? Description 有个$H$行$W$列的棋盘,里面有$N$个黑色格子,求一个棋子由左上方格子走到右下方格子且不经过黑色格子的方案数. $1=H,M=1e5,1=N=2000$.输出对$1e9+7$去模后的结果即可 ? Sol 假设没有黑色格子,方案数就为$C_{H+W-2}^{H-1}$. 简单说下,可

AcWing

?

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,b) for(Rg int i=a;i>=b;i++)
#define ll long long
using namespace std;
il int read()
{
    int x=0,y=1;char c=getchar();
    while(c<0||c>9){if(c==-)y=-1;c=getchar();}
    while(c>=0&&c<=9){x=(x<<1)+(x<<3)+c-0;c=getchar();}
    return x*y;
}
const int N=2010,M=200010;
int h,w,n,mod=(1e9)+7;
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=1;
    while(y){if(y&1)s=(s*x)%mod;x=(x*x)%mod;y>>=1;}
    return s;
}
il void init_C()
{
    jc[0]=1,inv[0]=1;
    go(i,1,200000)
        jc[i]=jc[i-1]*i%mod,inv[i]=ksm(jc[i],mod-2);
}
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+1]=(node){h,h+w};
    sort(a+1,a+n+1,cmp);
    go(i,n+1)
    {
        f[i]=C(a[i].s-2,a[i].x-1);
        go(j,i-1)
        {
            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("%lldn",(f[n+1]+mod)%mod);
    return 0;
}
View Code

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读