abc 230 f 题解
abc 230 f
题意
给定一个长度为 \(N\) 的序列 \(A\)。你可以做以下操作若干次(可以为 \(0\) 次):当序列长度至少为 \(2\) 时,选择两个相邻的元素,删除他们,并将他们的和插入到原来的位置。请你求出操作后有多少种可能的结果序列?答案对 \(998244353\) 取模。
-
\(1 \le N \le 2 \times 10 ^ 5\)
-
\(\lvert A_i \rvert \le 10 ^ 9\)
思路
前奏
有这样一道题目:给定一个序列 \(A\),请你求出序列 \(A\) 中有多少个本质不同的子序列。
例如:\(A = \{1, 1, 2, 2, 3\}\),选择 \(A_1, A_3, A_5\) 和选择 \(A_2, A_4, A_5\) 并不是本质不同的。
\(1 \le N \le 10 ^ 5\)
首先,这个题目,是肯定有一种暴力做法的 :搜索,但是,很显然是会超时的 \(O(2 ^ N)\)。
那么,我们先考虑一下用 dp
。
-
\(dp_i\) 表示以 \(A_i\) 结尾的本质不同的子序列数量。
那么,转移是什么呢?
\(A_1, A_2, \dots A_i = x, \dots A_j = x \dots A_N\)
很显然,\(dp_j\) 只能由 \(i \le k \le j - 1\) 的所有 \(dp_k\) 转移而来。
因为 \(A_1,A_2 \dots A_{i - 1}\) 转移到 \(A_j\) 和转移到 \(A_i\) 所得到的子序列本质是一样的。
所以我们用 \(last_{A_i}\) 表示 \(A_i\) 上一次出现的位置,\(last_{A_i}\) 为 \(0\) 则表示这是 \(A_i\) 第一次出现。
\[\begin{equation} dp_i= \begin{cases} \sum _ {j = 1} ^ {i - 1} dp_j + 1& \text{ $ last_{A_i} = 0 $ } \\ \sum _ {j = last_{A_i}} ^ {i - 1} dp_j& \text{ $ last_{A_i} > 0 $ } \end{cases} \end{equation}\] -
\(dp_i\) 表示用前 \(i\) 个元素组成本质不同的子序列的数量。
而这里的转移就比较明显了。
令 \(last_{A_i}\) 表示 \(A_i\) 上一次出现的位置,\(last_{A_i}\) 为 \(0\) 则表示这是 \(A_i\) 第一次出现。
\[\begin{equation} dp_i= \begin{cases} 2 \times dp_{i - 1} + 1& \text{ $ last_{A_i} = 0 $ } \\ 2 \times dp_{i - 1} - dp_{last_{A_i}} - 1& \text{ $ last_{A_i} > 0 $ } \end{cases} \end{equation}\]
正题
那么,题目给定的一次操作其实实际上是序列上的三次操作:
- 删除相邻元素的第一个
- 删除相邻元素的第二个
- 插入两个元素的和
但是,这样未免也太麻烦了。那该怎么办呢?
这里就可以用 前缀和 来优化了。
假设我们要取出的元素为 \(A_i,A_{i + 1}\),那么序列会变成这样:
\(A_1, A_2, \dots ,A_i + A_{i + 1}, \dots A_N\)
而这个新的序列的前缀和会变成这样:
\(A_1, A_1 + A_2, \dots ,A_1 + A_2 + \dots + A_{i - 1}, A_1 + A_2 + \dots + A_i + A_{i + 1}, \dots , A_1 + A_2 + \dots + A_N\)
原本序列的前缀和则是这样的:
\(A_1, A_1 + A_2, \dots ,A_1 + A_2 + \dots + A_{i - 1}, A_1 + A_2 + \dots + A_i, A_1 + A_2 + \dots + A_i + A_{i + 1}, \dots , A_1 + A_2 + \dots + A_N\)
可以发现,这三次操作可以变成前缀和数组上的一次操作:删除一个元素,而每一个本质不同的前缀和数组都会对应到一个本质不同的原序列,所以,这个题目可以变成:求出前缀和数组上的本质不同的子序列的数量。