1 条题解

  • 0
    @ 2025-10-21 9:44:40

    这道题是一个经典的 区间 DP 问题,并且因为合并规则的特殊性,需要一些状态设计的技巧。

    题目分析

    我们有一个长度为 nn 的 01 串,每次合并相邻的 kk 个字符,得到一个新字符和分数,最终合并到只剩 1 个字符,求最大分数。

    关键点

    1. 合并规则:给出所有 2k2^k 种可能的 kk 位二进制串对应的新字符和分数。
    2. 合并过程:每次合并 kk 个字符 → 1 个字符,长度减少 k1k-1
    3. 最终长度必须为 1,所以 (n1)mod(k1)(n-1) \bmod (k-1) 必须为 0。

    思路与状态设计

    直接设 dp[l][r]dp[l][r] 表示区间 [l,r][l, r] 的最大分数不够,因为不知道合并成什么字符,以及中间状态可能不是单个字符。

    巧妙的状态设计
    dp[l][r][s]dp[l][r][s] 表示将区间 [l,r][l, r] 合并成一个 二进制状态 ss 的最大分数,其中 ss 的长度为 len=(rl)mod(k1)+1len = (r-l) \bmod (k-1) + 1(如果模为 0,则长度为 k1k-1)。

    解释:

    • 区间长度 len=rl+1len = r-l+1
    • 每次合并减少 k1k-1 长度,所以最终合并成的“临时串”长度 = lenmod(k1)len \bmod (k-1),如果为 0 则长度为 k1k-1
    • 因此 ss 是一个 [0,2k1)[0, 2^{k-1}) 的整数,表示当前区间合并成的二进制串的值。
    • lenmod(k1)=1len \bmod (k-1) = 1 时,ss 只能是 0 或 1,表示最终合并成的单个字符。

    状态转移

    对于区间 [l,r][l, r],我们枚举一个分割点 mm,将区间分成 [l,m][l, m][m+1,r][m+1, r]

    设左区间状态为 xx,右区间状态为 yy,那么合并后的状态是 (x(len_right))y(x \ll (len\_right)) | y,其中 len_rightlen\_right 是右区间状态的长度(即 (rm)mod(k1)(r-m) \bmod (k-1),如果为 0 则 k1k-1)。

    如果合并后的状态长度等于 kk(即 len_left+len_right=klen\_left + len\_right = k),那么我们可以进行一次合并,得到新字符 cc 和分数 ww,更新 dp[l][r][c]dp[l][r][c]


    算法步骤

    1. 读入 n,kn, k 和初始串。
    2. 读入 2k2^k 种合并规则,存到数组 to_char[i]to\_char[i]score[i]score[i],其中 iikk 位二进制数。
    3. 初始化 DP:对于每个位置 iidp[i][i][s]=0dp[i][i][s] = 0,其中 ssstr[i]0str[i] - '0'
    4. 按区间长度从小到大进行 DP:
      • 枚举区间 [l,r][l, r]
      • 枚举分割点 m=l,l+1,,r1m = l, l+1, \dots, r-1
      • 枚举左区间状态 xx 和右区间状态 yy
      • 计算合并后的状态 comb=(xlen_right)ycomb = (x \ll len\_right) | y
      • 如果 len_left+len_right==klen\_left + len\_right == k,则可以进行最终合并:
        • 新字符 c=to_char[comb]c = to\_char[comb]
        • 新分数 sc=score[comb]sc = score[comb]
        • 更新 $dp[l][r][c] = \max(dp[l][r][c], dp[l][m][x] + dp[m+1][r][y] + sc)$
      • 否则,如果 len_left+len_right<klen\_left + len\_right < k,则不能合并成单个字符,只能作为中间状态:
        • 更新 $dp[l][r][comb] = \max(dp[l][r][comb], dp[l][m][x] + dp[m+1][r][y])$
    5. 最终答案在 dp[0][n1][0]dp[0][n-1][0]dp[0][n1][1]dp[0][n-1][1] 中取最大值。

    复杂度分析

    • 状态数:O(n22k1)O(n^2 \cdot 2^{k-1})
    • 转移:O(n22(k1))O(n \cdot 2^{2(k-1)})
    • 总复杂度:O(n34k1)O(n^3 \cdot 4^{k-1}),在 n300,k8n \le 300, k \le 8 时可行。

    总结

    这道题的关键在于:

    1. 发现合并过程长度减少 k1k-1 的规律。
    2. 设计状态 dp[l][r][s]dp[l][r][s] 表示合并成的二进制串。
    3. 在转移时判断能否进行最终合并。
    • 1

    信息

    ID
    3619
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者