P4685 [IOI2008] Linear Garden 题解

一道基础 dp 题远古 IOI 题。

用 $dp_{i,x,y}$ 表示考虑完了前 $i$ 位,以当前位结尾的后缀中 L 的个数减 P 的个数最大为 $x$,P 的个数减 L 的个数最大为 $y$,剩下的位有多少种合法的构造方案,由题意得 $0\le x,y<3$。直接暴力转移即可。

花园的序号 $=$ 字典序小于这个花园的个数 $+1$。考虑如何统计字典序小于这个花园的个数,可以枚举第一个不同的位,暴力求和即可。

代码:

#include<bits/stdc++.h>
#define mxn 1000003
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
#define drep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
int n,m,x,y,ans,f[mxn][3][3];
char s[mxn];
signed main(){
    scanf("%d%d%s",&n,&m,s+1);
    rept(i,0,3)rept(j,0,3)f[n][i][j]=1;
    drep(i,n-1,1){
        rept(x,0,3){
            rept(y,0,3){
                if(x!=2)f[i][x][y]=f[i+1][x+1][max(y-1,0)];
                if(y!=2)f[i][x][y]=(f[i][x][y]+f[i+1][max(x-1,0)][y+1])%m;
            }
        }
    }
    rep(i,1,n){
        if(s[i]=='L'){
            x++,y=max(y-1,0);
            if(x>2)break;
        }else{
            if(x!=2)ans=(ans+f[i][x+1][max(y-1,0)])%m;
            x=max(x-1,0),y++;
            if(y>2)break;
        }
    }
    cout<<(ans+1)%m;
    return 0;
}
posted @ 2023-07-24 17:47  zifanwang  阅读(13)  评论(0编辑  收藏  举报  来源