C. Beautiful Sequence 解题思路
摘要与问题转化
本题要求在一个仅包含数字 $ 1, 2, 3$ 的序列中,计算“完美子序列”的数量。一个完美子序列定义为形如 $ 1, 2, \dots, 2, 3$ 的序列,即以 $ 1$ 开头、以 $ 3$ 结尾,中间可以包含零个或多个 $ 2$。 由于序列的结构非常明确,我们不需要关注 $2$ 的具体数量,只需要统计以 $1$ 结尾的子序列数量、以 $2$ 结尾的子序列数量以及以 $3$ 结尾的(即完美)子序列数量。当遍历到当前的数字 $x$ 时,它可以通过衔接一个以 $x-1$ 结尾的子序列,从而形成新的以 $x$ 结尾的子序列。同时,如果 $x=2$,它可以衔接**任何一个**已存在的以 $2$ 结尾的子序列,从而生成新的以 $2$ 结尾的子序列。主体分析:动态规划策略
1. 状态定义
我们采用动态规划(Dynamic Programming, DP)来解决这个问题,其时间复杂度为 $O(N)$,可以满足 $N \le 2 \cdot 10^5$ 的数据规模要求。 定义 $dp[i]$ 为:以数字 $i$ 结尾的合法子序列的数量。其中 $i \in \{1, 2, 3\}$。- $dp[0]$:辅助状态,初始化为 $1$。它表示一个“空子序列”或“起始点”。当遇到 $1$ 时,新的以 $1$ 结尾的子序列数量可以从这个起始点计数 $1$ 开始。
2. 状态转移方程
我们遍历输入的序列,对于当前的数字 $x$:
A. 特殊情况:数字 $x=2$ 的自我转移
数字 $2$ 具有特殊的性质,它可以接在任何一个已存在的以 $2$ 结尾的子序列后面,形成一个新的以 $2$ 结尾的子序列。 如果当前读入的数字 $x=2$,则: $$ dp[2] \leftarrow dp[2] + dp[2] $$ 这个操作表示:对于已有的 $dp[2]$ 个以 $2$ 结尾的子序列,新的 $2$ 都可以接在它们后面,使得数量翻倍。由于 $2$ 的自我衔接不依赖于 $1$ 的转移,因此应先进行。B. 核心递推:从 $x-1$ 转移到 $x$
数字 $x$ 可以接在所有以 $x-1$ 结尾的子序列后面,形成新的以 $x$ 结尾的子序列。 $$ dp[x] \leftarrow dp[x] + dp[x-1] $$- **当 $x=1$ 时:** $dp[1] \leftarrow dp[1] + dp[0]$。所有以 $1$ 结尾的子序列数量增加了 $dp[0]=1$(新的 $1$ 本身作为子序列)个。
- **当 $x=2$ 时:** $dp[2] \leftarrow dp[2] + dp[1]$。以 $2$ 结尾的子序列数量增加了所有以 $1$ 结尾的子序列的数量。
- **当 $x=3$ 时:** $dp[3] \leftarrow dp[3] + dp[2]$。以 $3$ 结尾的完美子序列数量增加了所有以 $2$ 结尾的子序列的数量。
3. 实现细节与模运算
由于结果可能非常大,我们需要在每一步加法操作时对结果取模 $MOD = 998244353$。C++ 代码实现
1 |
|

