Codeforces 1383E Strange Operation

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 串的数量。
考虑两种情况:

  1. \(S\) 全是 0。答案是 \(|S|\)
  2. \(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}_{至少\ 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 的个数。

posted @ 2020-07-29 02:20  Pat  阅读(252)  评论(0编辑  收藏  举报