TonyYin's Blog

Back

题意#

给定一个合法括号序列,对序列按照如下方法染色:

  1. 每个括号的颜色:红色、蓝色、或不染色;
  2. 每对匹配的括号:有且仅有其中一个被染色;
  3. 相邻两个括号:若都有颜色,要求它们的颜色互不相同。

求符合条件的染色方案数,对 109+710^9+7 取模。

序列长度:2s7002\leq |s|\leq 700.

分析#

区间DP.

将颜色映射到三个数:

Color={0No Color1Red2Blue\operatorname{Color}=\left\{\begin{array}{ll} 0 & \text{No Color}\\ 1 & \text{Red}\\ 2 & \text{Blue}\\ \end{array}\right.

f[l][r][x][y]f[l][r][x][y] 为区间 [l,r][l, r] 内,且 Colorl=x,Colorr=y\operatorname{Color}_l=x, \operatorname{Color}_r=y 的方案数。

下面分类讨论状态转移方式:#

情况一:()()#

l+1=rl+1=r,则这段序列仅有一对左右括号,只能对其中一个染色。

作为初始情况,可直接赋值:

f[l][r][0][1]=f[l][r][0][2]=f[l][r][1][0]=f[l][r][2][0]=1f[l][r][0][1]=f[l][r][0][2]=f[l][r][1][0]=f[l][r][2][0]=1

情况二:()(\dots\dots)#

llrr 配成一对括号,则枚举 Colorl+1\operatorname{Color}_{l+1}Colorr1\operatorname{Color}_{r-1},从 f[l+1][r1]f[l+1][r-1] 进行转移。

f[l][r][x][y]=i=0ixj=0jyf[l+1][r1][i][j]f[l][r][x][y]=\sum_{i=0\vee i\neq x}\,\sum_{j=0\vee j\neq y} f[l+1][r-1][i][j]

情况三:()()(\dots\dots) \dots(\dots)#

要求 ll 是左括号,rr 是右括号。设 R[i]\operatorname{R}[i] 表示与 ii 配对的右括号。

f[l][R[l]]×f[R[l]+1][r]f[l][\operatorname{R}[l]]\times f[\operatorname{R[l]+1}][r] 进行转移,具体过程要枚举四个颜色,就不做形式化表达了。

for(int i = 0; i <= 2; i++) {
    for(int j = 0; j <= 2; j++) {
        for(int p = 0; p <= 2; p++) {
            for(int q = 0; q <= 2; q++) {
                if((j == 1 && p == 1) || (j == 2 && p == 2)) continue;
                (f[l][r][i][q] += (f[l][R[l]][i][j] * f[R[l] + 1][r][p][q]) % mod) %= mod;
            }
        }
    }
}
cpp
【CodeForces-149D】Coloring Brackets
https://www.tonyyin.top/blog/oi-solution/cf149d
Author TonyYin
Published at October 28, 2022
Comment seems to stuck. Try to refresh?✨