川剧复演 题解

川剧复演 题解

题意

有 n 场演出、m 出剧目。每场选一出剧目,同一剧目可重复选。

合法条件:任意连续 m 场演出中,都存在某剧目出现至少两次。

换句话说,不允许出现"连续 m 场两两不同"。

暴力 DP

状态

把"全局约束"翻译成"局部禁止条件"

合法 ⟺ 不存在长度为 m 的连续子段两两不同。

我们从左往右一场一场地安排演出。假设已经安排好了前 i 场,现在要安排第 i+1 场。什么时候会出问题? 出问题当且仅当第 i+1 场安排完后,末尾出现了 m 个两两不同的元素。

所以危险全部来自于序列末尾那一段"两两不同"的后缀。

找到"充分统计量"

我们并不需要知道末尾具体是哪几出剧目,只需要知道一个数字:

末尾最长的、元素两两不同的后缀的长度 j

为什么这个数字就够了?

  • 如果 \(j < m-1\):不管下一场选什么,新的"两两不同后缀"最多变成 \(j+1 < m\),不可能出问题。
  • 如果 \(j = m-1\):下一场绝对不能选一个全新的剧目 ,否则 \(j\) 就变成 \(m\) 了,非法。

也就是说,未来的所有决策只依赖于 j,不依赖于具体是哪 j 出剧目。这就是这个状态巧妙的地方------它丢掉了所有无关信息,只保留了对决策有用的那一个量。

状态定义

\f\[ij = \text{安排了前 } i \text{ 场,且末尾最长两两不同后缀长度恰好为 } j \text{ 的合法方案数} \]

其中 \(0 \le j < m\)(j = m 就非法了,所以状态里不包含 j = m)。

边界 :\(f00 = 1\)(空序列,什么都没安排,后缀长度为 0)。

转移

考虑从 \(fi-1k\) 转移过来。当前末尾有 k 个两两不同的元素,现在追加一个新元素 \(x\)。分两种情况:

1. \(x\) 重复了后缀中的某一个元素

后缀中 \(k\) 个元素两两不同,所以 \(x\) 恰好等于其中某一个。假设 \(x\) 等于后缀中倒数第 \(s\) 个 元素(\(1 \le s \le k\))。

那么新的"两两不同后缀"就是从倒数第 \(s-1\) 个元素到新元素 \(x\),一共 \(s\) 个元素,且这 \(s\) 个元素两两不同。

对于每个 \(s \in 1, k\),\(x\) 的选择恰好只有 1 种 (就是那个等于倒数第 \(s\) 个元素的剧目),所以:

\f\[is \mathrel{+}= fi-1k \qquad (1 \le s \le k) \]

2. x 是后缀中没有的全新剧目

此时新的两两不同后缀长度变成 \(k+1\),有 \((m - k)\) 种选择(总剧目数减去后缀中已有的 \(k\) 个)。

但注意:只有当 \(k + 1 < m\) 时才合法,否则就凑齐了 \(m\) 个不同元素。所以:

\f\[ik+1 \mathrel{+}= fi-1k \times (m - k) \qquad (\text{仅当 } k+1 < m) \]

ans

\\\text{ans} = \\sum_{j=0}\^{m-1} f\[nj \]

即把所有可能的后缀长度加起来。

复杂度

  • 状态数:\(O(n \cdot m)\)
  • 每个状态转移:情况一需要遍历 \(1 \sim k\),共 \(O(m)\);情况二 \(O(1)\)
  • 总复杂度:\(O(n \cdot m^2)\)

正解:后缀优化 + 矩阵加速

后缀优化

暴力 DP 的转移中,情况一需要对每个 \(s \in 1, k\) 累加 \(fi-1k\),这是 \(O(m)\) 的。我们用后缀和 把它压成 \(O(1)\)。

定义后缀和

设

\s\[ij = \sum_{t=j}^{m-1} fit \]

即从 \(j\) 到 \(m-1\) 的总和。显然 \(sij - sij+1 = fij\)。

把转移改写为后缀和的形式

情况一:\(fis \mathrel{+}= fi-1k\)(对所有 \(k \ge s\)),等价于

\f\[is \mathrel{+}= \sum_{k=s}^{m-1} fi-1k = si-1s \]

情况二:\(fik+1 \mathrel{+}= fi-1k \times (m-k)\),即

\f\[ij \mathrel{+}= fi-1j-1 \times (m - j + 1) \qquad (j \ge 1) \]

合并两种情况:

\f\[ij = si-1j + (m - j + 1) \cdot fi-1j-1 \]

其中约定 \(fi-1-1 = 0\)。

这样对每个 \(j\) 只需要 \(O(1)\) 计算,总复杂度降为 \(O(n \cdot m)\)。

矩阵加速

\(n\) 可以达到 \(10^9\),\(O(n)\) 的线性 DP 无法接受。但注意到状态只有 m 个 (\(j = 0, 1, \dots, m-1\)),而且转移是线性的,所以可以用矩阵快速幂。

构造转移矩阵

把 \(fi-10, fi-11, \dots, fi-1m-1\) 看作一个行向量,转移到 \(fi0, fi1, \dots, fim-1\)。

由 \(fij = si-1j + (m-j+1) \cdot fi-1j-1\),而 \(si-1j = \sum_{t=j}^{m-1} fi-1t\),所以:

\f\[ij = \underbrace{1 \cdot fi-1j + 1 \cdot fi-1j+1 + \cdots + 1 \cdot fi-1m-1}{\text{情况一:所有 } k \ge j} + \underbrace{(m-j+1) \cdot fi-1j-1}{\text{情况二}} \]

写成矩阵 \(T\)(大小 \(m \times m\)),其中 \(Tkj\) 表示 \(fi-1k\) 对 \(fij\) 的贡献系数:

  • 情况一:当 \(k \ge j\) 时,\(Tkj += 1\)
  • 情况二:当 \(k = j-1\) 时,\(Tkj += (m - j + 1)\),即 \(Tj-1j += m - j + 1\)

矩阵的样子如下(以 \(m = 5\) 为例):

\T = \\begin{pmatrix} 0 \& 5 \& 0 \& 0 \& 0 \\\\ 1 \& 1 \& 4 \& 0 \& 0 \\\\ 1 \& 1 \& 1 \& 3 \& 0 \\\\ 1 \& 1 \& 1 \& 1 \& 2 \\\\ 1 \& 1 \& 1 \& 1 \& 1 \\\\ \\end{pmatrix} \\

第 \(k\) 行第 \(j\) 列:下三角(\(k \ge j\))全是 1(情况一),再加上紧邻的右上角元素(\(k = j-1\))为 \(m-j+1\)(情况二)。

初始向量为 \(f0 = (1, 0, 0, \dots, 0)\),答案为 \(fn\) 的所有分量之和。

快速幂

\f\[n = f0 \times T^n \]

用矩阵快速幂计算 \(T^n\),复杂度 \(O(m^3 \log n)\)。

复杂度

  • 后缀优化后单次转移:\(O(m)\)
  • 矩阵快速幂:\(O(m^3 \log n)\)
  • 总复杂度:\(O(m^3 \log n)\)

对 \(m \le 200\)、\(T \le 5\),\(200^3 \times 30 \times 5 \approx 1.2 \times 10^9\),略紧但实际可通过。

扩展:线性递推 + 多项式快速幂 \(O(m^2 \log n)\)

矩阵 \(T\) 具有特殊结构,可以推出 \(a_n = \sum_{j=0}^{m-1} fnj\) 满足一个 \(m-1\) 阶线性递推:

\a_n = d_1 a_{n-1} + d_2 a_{n-2} + \\cdots + d_{m-1} a_{n-m+1} \\

其中系数:

  • \(d_1 = m - 1\)
  • \(d_j = (j-1)! \cdot (m - j)\) (\(2 \le j \le m-2\))
  • \(d_{m-1} = (m-2)!\)

用多项式快速幂计算 \(x^{n-1} \bmod p(x)\),其中特征多项式:

\p(x) = x\^{m-1} - d_1 x\^{m-2} - d_2 x\^{m-3} - \\cdots - d_{m-1} \\

若 \(x^{n-1} \equiv c_0 + c_1 x + \cdots + c_{m-2} x^{m-2} \pmod{p(x)}\),则

\a_n = \\sum_{i=0}\^{m-2} c_i \\cdot a_{i+1} \\

其中 \(a_i = m^i\)(\(i < m\) 时无约束,所有安排都合法)。复杂度 \(O(m^2 \log n)\),对 \(m = 200\) 绰绰有余。

相关推荐
All for pursuit.20 小时前
【动态规划-21】312.戳气球
数据结构·c++·算法·leetcode·动态规划
y1su1 天前
Leetcode 动态规划 模板
java·数据结构·算法·leetcode·动态规划
w_zero_one1 天前
动态规划(三)
java·算法·动态规划
Tisfy1 天前
LeetCode 2913.子数组不同元素数目的平方和 I:第一题先常数很大的O(n^2)
算法·leetcode·题解·模拟·暴力
木井巳1 天前
【动态规划】三步问题
java·算法·leetcode·动态规划·推荐算法
浅念-2 天前
动态规划:线性DP——多状态DP与子数组专题笔记
c++·笔记·算法·leetcode·职场和发展·动态规划·力扣
不会就选b2 天前
算法日常・每日刷题--<动态规划>26
算法·动态规划
Tisfy2 天前
LeetCode 3723.数位平方和的最大值:构造
数学·算法·leetcode·字符串·题解
不会就选b3 天前
算法日常・每日刷题--<动态规划>23
算法·动态规划