https://codeforces.com/contest/1383/problem/E
本文是我对 tourist 的解法的解释。
题目大意
给定一个01串 $S$,长度是 $n$。定义操作:将串中相邻两数变成二者的最大值。每次操作过后串长减少 $1$。
$00 \to 0$
$01 \to 1$
$10 \to 1$
$11 \to 1$
试问经过至少 $0$ 次,至多 $n - 1$ 次操作之后可以得到多少种不同的01串。
分析
首先注意到原串中的1不可能全部消除。
用 $f(S)$ 表示01串 $S$ 经过至多 $|S|-1$ 次操作过后可以得到的不同 01 串的数量。
考虑两种情况:
- $S$ 全是 0。答案是 $|S|$。
- $S$ 不全是 0。设 $S$ 的开头有 $a$ 个 0,结尾有 $b$ 个 0。将 $S$ 去掉开头和结尾的 0 所得01串记作 $T$。答案是 $(a+1)(b+1)f(T)$。
以下假设 $S$ 以1开头且以1结尾,$S$ 的长度是 $n$。结果串也必然以1开头且以1结尾。
用 $S[l,r]$ 表示 $S$ 的下标从 $l$ 到 $r$ 的子串。
将最终结果分成若干类
第一类,全是1。
第二类,至少包含一个零。
第二类又可以按照第一个0之前有几个1加以细分:
10...1
110...1
1110...1
...
只要解决10...1这一类,就可以解决剩下的几类,因为它们是子问题。
我们按1后面紧跟着的0个个数分类。
101...
1001...
...
假设 $S$ 的第一个1之后有2个0,即 $S$ 形如 1001...
则 101...,1001... 这两类的数量都是 $f(S[4,n])$。
现在要问,10001... 这类结果串有多少个?
设 $S$ 中第一个其后紧跟着的0的数量大于等于3的1之后的那个1的下标是 $i$,则形如10001...的结果串有 $f(S[i,n])$ 个。
于是想到:从右往左,对于 $S$ 的每个以 1 开头的后缀 $S[i,n]$ 计算 $f(S[i,n])$。维护一个数组 $g$,设最近一次遇到的在其之前至少有 $k$ 个0的那个1的下标是 $j$($\dots 1\underbrace{0\dots 0}_{\text{至少 $k$ 个 $0$}}\color{red}{1}\dots$,红色的 $1$ 的下标是 $j$),则 $g[k] = f(S[j..n])$,若满足条件的 $j$ 不存在,则 $g[k] = 0$。将数组 $g$ 的元素之和记作 $G$。每次遇到 $S_i = 1$,更新 $g$ 和 $G$,$f(S[i,n])$ 等于迄今在每个 1 处的 $G$ 之和再加上 $S[i,n]$ 内 1 的个数。