Gerald and Giant Chess

Posted a1b3c7d9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gerald and Giant Chess相关的知识,希望对你有一定的参考价值。

(Gerald and Giant Chess
)[https://www.luogu.org/problemnew/show/CF559C]

给你一个\(n\times m\)的网格图,有t个棋子被标记成黑色,第i个黑色格子记做\((x_i,y_i)\),其余白色,现在询问在只能向下走或向右走的前提下,从\((1,1)\)\((n,m)\)的不经过黑色格子的路径条数,\(n,m\leq 10^5,p\leq 2000\)

显然不会以传统做法,在哪一个格子为状态,突破点在只有2000个黑色格子,自然考虑补集思想。

为了递推的无后效性,我们把黑色格子按行再列优先的顺序从小到大排序,接着考虑构造不合法状态,于是设\(f_i\)表示以第i个黑色格子结尾的路径条数,因此转移为

\[f_i=\sum_j=1^i-1 f_j\times C_x_i+y_i-x_j-y_j^x_i-x_j\]

答案:\(\sum_i=1^tf_i\times C_n+m-x_i-y_i^n-x_i\)

但是这样的方程是存在重复,于是需要特殊化划分去重,这里考虑限定一个不合法的方法(简称限一),于是设\(f_i\)表示只经过i这个黑色格子,以i结尾的路径条数,所以就有转移

\[f_i=C_x_i+y_i-2^x_i-1-\sum_j=1^i-1f_j\times C_x_i+y_i-x_j-y_j^x_i-y_i\]

边界:\(f_1\)爆算

答案:\(\sum_i=1^tf_i\times C_n+m-x_i-y+i^n-x_i\)

于是预处理出组合数,以此\(O(n^2)\)转移即可。

参考代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#define il inline
#define ri register
#define ll long long
#define Size 200010
#define yyb 1000000007
using namespace std;
struct point
    int x,y;
    il bool operator<(const point&a)const
        return y==a.y?x<a.x:y<a.y;
    
p[2005];
ll dp[2005],jc[Size],jv[Size];
il void prepare(int);
il ll pow(ll,ll),c(int,int);
int main()
    int h,w,n;
    scanf("%d%d%d",&h,&w,&n),prepare(h+w);
    while(1-1)printf("yyb爆踩gsy");
    for(int i(1);i<=n;++i)scanf("%d%d",&p[i].x,&p[i].y);
    sort(p+1,p+n+1),dp[1]=c(p[1].y+p[1].x-2,p[1].y-1);
    if(p[n].x==h&&p[n].y==w)return puts("0"),0;p[++n].x=h,p[n].y=w;
    for(int i(2),j;i<=n;++i)
        dp[i]=c(p[i].y+p[i].x-2,p[i].x-1);
        for(j=1;j<i;++j)
            (dp[i]-=dp[j]*c(p[i].y+p[i].x-p[j].y-p[j].x,p[i].y-p[j].y))%=yyb;
    printf("%lld",(dp[n]+yyb)%yyb);
    return 0;

il ll c(int n,int r)
    if(n<r||n<0||r<0)return 0;
    return jc[n]*jv[r]%yyb*jv[n-r]%yyb;

il ll pow(ll x,ll y)
    ll ans(1);while(y)
        if(y&1)(ans*=x)%=yyb;
        y>>=1,(x*=x)%=yyb;
    return ans;

il void prepare(int n)
    int i;jc[0]=jv[0]=1;
    for(i=1;i<=n;++i)jc[i]=jc[i-1]*i%yyb;jv[n]=pow(jc[n],yyb-2);
    for(i=n-1;i;--i)jv[i]=jv[i+1]*(i+1)%yyb;

以上是关于Gerald and Giant Chess的主要内容,如果未能解决你的问题,请参考以下文章

CF 559C - Gerald and Giant Chess (组合计数)

Codeforces 559C Gerald and Giant Chess

题解 CF559C Gerald and Giant Chess

CF559C Gerald and Giant Chess

《算法竞赛进阶指南》0x5C计数DP Gerald & Giant Chess

codeforces 7 A. Kalevitch and Chess