甲:ABC214 F - Substrings

乙:ARC117 C - Tricolor Pyramid

丙1:ARC110 E - Shorten ABC

丙2:AGC027 E - ABBreviate

丁:ABC171 F - Strivore

戊:CF1481 E - Sorting Books

己:ARC112 E - Cigar Box

庚:ABC234 F - Reordering

甲 解1

设\(f_i\)表示选择了第\(i\)个字符,前缀\(S[1\dots i]\)的答案子序列个数。

一种想法是将每个\(f_j,j<i-1\)都统入\(f_i\)中,但这样会导致算重复。

那么我们修改一下原来的定义:

设\(f_i\)表示选择了第i个字符,字符串\(T\)是\(S[1\dots i]\)的答案子序列,并且\(T\)不是\(S[1\dots (i-1)]\)的答案子序列。

换种说法,状态\(f_i\)表示前缀\(S[1\dots i]\)与前缀\(S[1\dots (i-1)]\)的差集。

  • 这个做法好像叫序列自动机

那么继续写下一个\(\color{#ffffff}{假}\)做法x

一个转移:

\(f_i=\sum_{j=1}^{i-2}f_j+1\)

那么我们来证明一下这个\(\color{#ffffff}{假}\)做法的正确性:

  • 根据定义,\((1\dots(i-2))\)统计的答案子序列互相之间不会重合。全都在后面加一个\(s_i\)同理。

  • 假设存在一个字符串被同时统计进了\(f_i\)与某个\(f_j(j<i)\)中,那么这个字符串形如\(T+s_i\)。

    当然也可以写为\(T+s_j\)。也就是\(s_i=s_j\)。

    可以确定的是,这里的\(T\)包含于\((1...(j-2))\)这样一个前缀中。(这个\(T\)可以为空,不多解释)

    所以我们可以确定:\(f_i\)不能由\(f_{1...j-2},s_j=s_i\)转移过来。

进一步更新这个做法:

\(f_i=\sum_{max_j(s_j=s_i)-1}^{i-2}f_j\)

特别地,对于\(s_i\)在字符串第一次出现,\(f_i=\sum_{j=1}^{i-2}f_j+1\)。

证法同上了。

这样 应该 可以了吧x

甲 解2

更简单的一种使得答案不重的思路是,强制规定选出来的子串在原串中最早出现

每个位置转移到后面最近的分别26个字符即可。

事实上,丙丁两题的思想与这个差不多(

将\(RBW\)三种颜色分别标为\(0\),\(1\),\(2\)

两块合并的操作会等价变为两数之和取负\(mod \ 3\)

于是可以把所有块都合并起来再\(mod \ 3\)得到结果。

问题其实转化为一个块到顶端的路径数,在边平行于金字塔的斜平行四边形中讨论发现是二项式系数(

由于这里的模数\(p\)为一个很小的数。当模数小于组合数中的\(n\),\(m\)时,在阶乘中模去\(p\)显然会在某个地方开始出现阶乘为0的情况,将无法处理。

对于这种模数\(p\)小于\(n\),\(m\)的情况,需要用到\(\text{Lucas}\)定理:\({n \choose m} \ mod \ p \ = {{{\frac{n}{p}} \choose {\frac{m}{p}}} \times {{n \ mod \ p} \choose {m \ mod \ p}}} \ mod \ p\)

丙2

题意:给定一个 \(a,b\) 构成的字符串 \(s\),每次可以选择两个连续的 \(a\) 换成 \(b\),或两个连续的 \(b\) 换成 \(a\),问可以构造出多少不同的字符串。

首先我们容易看出,形如\(\text{ababab}\dots\) 的 \(s\) 是无法操作的,此时答案为\(1\)。

在下面,我们不再讨论这样一种特殊情况。

与乙题解法类似,我们设\(mod3\)意义下的\(p(s)\):

设\(p(a)=1\),\(p(b)=2\),\(p(s)\)为s中所有字母\(p\)值和\(mod3\)

那么\(p(aa)=p(b)=2\),\(p(bb)=p(a)=1\),正好对应了合并的这样一个操作。

一个结论:一个字符串\(s\),若其中存在两个相邻且相同的字符,那么s一定可以合并为单个字符串\(c\),且\(p(c)=p(s)\)。

那么我们可以设想一种方法:将一个字符串\(s\)划分为\(m\)个\(p\)值都不为\(0\)的子段,再将每个子段合并。

证明:任意一种可行的划分都可以成功合并。
  • (1) 对于每个子段都存在相邻两个字母相同的划分____可以。
  • (2) 否则,划分出不满足此条件的子段必定为\(\text{abab}\dots\text{baba}\)或者\(\text{baba}\dots\text{abab}\)这样首尾相同的交替串。

    由于两情况对等,我们首先考虑\(\text{abab}\dots\text{baba}\),并特殊化为\(\text{aba}\)(合并后为\(\text{a}\))的形式,并且原串内两个相邻相同的字符在该子段的右边(在左边同理,并且不需要考虑相同字符被合并完了,因为那样可以把它拆回去。)

    此时我们考虑到右边到第一对相同字符的位置为止。

    ① 合并后为\(\text{a}|\text{a}\dots\),则将\(\text{aba}|\text{a}\dots\)中\(\text{ba}|\text{a}\)的部分合并为\(\text{a}\)。

    ② 合并后为\(\text{a}|\text{baba}\dots\text{ababaa}\),合并\(\text{baa}\)为\(\text{a}\)。末尾为\(\text{bb}\)同理
证明结束。

接着我们考虑分段重合的情况。

如果存在一个字符串\(t\),满足\(p(t)=0\)

那么\((s1)(t)(s2)\)这样的情况下,\((s1)(t)|(s2)\)和\((s1)|(t)(s2)\)这两种划分是一样的(p值是一样的)。

那么我们强制规定左侧的子段\(s1\)不含有\(p\)值为\(0\)的非空后缀。

这样划分出来可能会导致全串最后剩下一个\(p\)值为0的后缀。但它可以被合掉(不写证明了,被自己废话恼了)

于是就可以\(\text{DP}\)了

设\(f_i\)表示原串\(1 \dots i\)位置的答案

处理每个位置\(i\),从\(i+1\)位开始 最短的\(p\)值为\(1\)与\(p\)值为\(2\)的串 的末尾 的位置\(nex_{i,1/2}\)。

那么转移是\(f_i \to f_{nex}\)

答案为每个\(p(s{(i+1) \dots n})=0\)的\(f_i\)之和。

另一道题其实类似,令\(p(a)=1\),\(p(b)=2\),\(p(c)=3\),那么两个字母合并的操作就变成了异或(\(\oplus,xor\)),和这题有基本一致的性质。

我们考虑最朴素的做法:选择任意\(k\)个字符插入该字符串任意位置,具体实现是排列完使用隔板法。

但这样会导致答案重复。

于是我们考虑一个最终情况的字符串,例如\(\text{minoriko}\),原串\(\text{io}\)

由\(\text{io}\)到\(\text{minoriko}\)有三种方式:(手写列一下好了)

那么为了使得答案不重,一种思路是:使得\(\text{io}\)到\(\text{minoriko}\)只有一种方法。

也就是\(\text{m} \color{red}{\text{i}} \text{n} \color{red}{\text{o}} \text{riko}\)

那么就得到一个做法:每个字母前面只能插入和它不相同的字符。最后一个字符串后面则可以插入任何字符。

由此得来有意思的结论是,相同长度的字符串得到的答案是相同的。

所以,我们枚举插入在字符串最后的字符个数,再使用隔板法就好了。

得到柿饼:

\[\sum_{i=0}^{k}26^i\times25^{k-i}\times C(n+k-i-1,n-1)
\]

当我们选择了一些需要移动的书本,这些书本放到末尾的顺序是可以任意决定的。

在需要移动的书本之外,自然是选择不需要移动的书本。

不需要移动的书本呢,会是一组一组并不互相重合的相同颜色的区间

不过这里有一个特殊情况,就是最后在所有不移动书本的末尾,由于【任意决定顺序】这个性质,这个末尾并不需要包含全部的该颜色书。

设\(f_i\)表示\([i,n]\)区间最多不移动的书本数目,得到以下转移:

\[f_i=max\left\{
\begin{aligned}
f_{i+1}\\
sumr_{a_i}\\
sumr_{a_i}+f_{r_{a_i}+1}\\
\end{aligned}
\right.
\]

移动问题的\(\text{point}\):选择出移动的元素和不移动的元素。

由原串到目标的这样一个变换,我们可以认为目标串中的某个不降子序列没有被移动过。

首先这题有和戊题一样的一个点,移动的元素顺序可以任意决定

另外,对于某个元素,影响其状态的是只有其最后一次操作。

为了方便,我们暂时称这个元素的最后一次操作为它的关键操作。

研究这个操作的一些性质。

如果在原序列中某一个元素\(x\)完成了其向左的关键操作,那么在目标序列中,\(x\)左侧的元素是必定要操作的。同理,另一个元素完成向右的关键操作,在关键序列中在其右侧的元素也必须进行操作。

在这两个元素之间的所有元素,则不会进行任何操作。

于是我们得到了可以作为不移动的元素的特征:是一组在目标串中连续的元素,并且在目标串中单调递增(准确来说是:元素相对于原串的位置单调递增,由于这里原串元素是单增排列所以可以这样写)

接着考虑移动的元素,会如何移动:

1.完成一个左移关键操作(在不移动元素被确定,当前序列在某个方案中确定的情况下,方案是唯一的。也可以理解为,所有元素完成关键操作的顺序是确定的);

2.完成一个右移关键操作(同左移);

3.不完成任何关键操作(在移动元素中任选一个向左或向右移都可以)。

计数的时候可以只考虑移动的元素。所以我们在下面研究转移的时候,可以将序列看作只包含需要移动的元素。作这个说明只是为了在计数的时候更加清晰

这样得到一个朴素的\(\text{DP}\):

设\(f_{i,l,r}\)表示进行了\(i\)次操作,有\(l\)个元素还未完成左移关键操作,\(r\)个元素还未完成右移关键操作时的操作方案数,那么:

\[f_{i,l,r}=f_{i-1,l,r}\times(l+r)\times2+f_{i-1,l+1,r}+f_{i-1,l,r+1}
\]

答案即\(f_{m,0,0}\)。

我们发现后两项左移右移的转移类似,即左移操作和右移操作本质是一种对称的操作,那么我们可以进一步优化

只关注还有多少个元素未发生关键操作。设\(f_{i,l+r}\)表示进行了\(i\)次操作,有\(l+r\)个元素还未完成关键操作时的操作方案数。

对于结果\(f_{m,0}\),由于我们没有考虑左移右移的操作的顺序,需要乘上\({l+r}\choose l\)(即从\(l+r\)个操作中选出\(l\)个向左,其余向右)。

但我们注意到,这个\(\text{DP}\)的初始状态为\(f_{0,l+r}=1\),对于每一组\(j=l+r\),都需要重新进行\(\text{DP}\),造成了三次的时间复杂度,无法通过。

反过来考虑(倒序还原),使\(\text{DP}\)的初始状态为\(f_{0,0}=0\),即:设\(f_{i,l+r}\)表示还有\(i\)次操作,有\(l+r\)个元素还未完成关键操作时的操作方案数。

与上面相同的考虑移动的方法(这里考虑的是后面这一步做了什么,反推前面这一步):

1.(在下一步中)完成了一个左移关键操作;

2.(在下一步中)完成一个右移关键操作;

3.(在下一步中)不完成任何关键操作,回退到上一步则为选取两端元素之一插回原序列的任意位置。方案数为\((l+r)\times2\)

使用刷表法转移(这里\(l+r\)写作\(j\),实际实现也是这样。\(l\)与\(r\)的拆分只在最后组合数那一步的计算需要用到):

\[f_{i,j} \times j \times 2 \to f_{i+1,j}
\]
\[f_{i,j} \to f_{i+1,j+1}
\]

当然,填表也行(

\[f_{i,j}=f_{i-1,j}\times 2 \times j + f_{i-1,j-1}
\]

突然加的(

设\(f_i\)表示构造长度为\(i\)字符串的方案数

枚举每个字母添加的个数\(k\),那么有:

\[{f_i \times {{i+k} \choose k}} \to f_{i+k}
\]

没了(

【KFC】JZ408 Koufu Contest 3 题解的更多相关文章

  1. AtCoder Beginner Contest 154 题解

    人生第一场 AtCoder,纪念一下 话说年后的 AtCoder 比赛怎么这么少啊(大雾 AtCoder Beginner Contest 154 题解 A - Remaining Balls We ...

  2. AtCoder Beginner Contest 153 题解

    目录 AtCoder Beginner Contest 153 题解 A - Serval vs Monster 题意 做法 程序 B - Common Raccoon vs Monster 题意 做 ...

  3. AtCoder Beginner Contest 177 题解

    AtCoder Beginner Contest 177 题解 目录 AtCoder Beginner Contest 177 题解 A - Don't be late B - Substring C ...

  4. AtCoder Beginner Contest 184 题解

    AtCoder Beginner Contest 184 题解 目录 AtCoder Beginner Contest 184 题解 A - Determinant B - Quizzes C - S ...

  5. M-SOLUTIONS Programming Contest 2020 题解

    M-SOLUTIONS Programming Contest 2020 题解 目录 M-SOLUTIONS Programming Contest 2020 题解 A - Kyu in AtCode ...

  6. AtCoder Beginner Contest 173 题解

    AtCoder Beginner Contest 173 题解 目录 AtCoder Beginner Contest 173 题解 A - Payment B - Judge Status Summ ...

  7. AtCoder Beginner Contest 172 题解

    AtCoder Beginner Contest 172 题解 目录 AtCoder Beginner Contest 172 题解 A - Calc B - Minor Change C - Tsu ...

  8. AtCoder Beginner Contest 169 题解

    AtCoder Beginner Contest 169 题解 这场比赛比较简单,证明我没有咕咕咕的时候到了! A - Multiplication 1 没什么好说的,直接读入两个数输出乘积就好了. ...

  9. AtCoder Beginner Contest 148 题解

    目录 AtCoder Beginner Contest 148 题解 前言 A - Round One 题意 做法 程序 B - Strings with the Same Length 题意 做法 ...

  10. AtCoder Beginner Contest 115 题解

    题目链接:https://abc115.contest.atcoder.jp/ A Christmas Eve Eve Eve 题目: Time limit : 2sec / Memory limit ...

随机推荐

  1. Python+Django(2)——创建应用程序

    新打开一个终端窗口,切换到manage.py所在的目录 激活虚拟环境:ll_env\Scripts\activate 命令startapp appname 让Django建立创建应用程序所需的基础设施 ...

  2. 终端命令mix

    Jdk(1.7) java -version Maven是否安装 mvn -v MySQL(5.7) mysql -uroot -p /Users/zhanzhanyunjiu/Documents/a ...

  3. 工控小工具 snmp 、opc ua 、modbus 、tcp、bacnet 开发环境Net6.0

    下载地址 https://files.cnblogs.com/files/blogs/745639/net6.0-windows.rar?t=1674114312

  4. jmeter性能测试学习1_配置oracl jdbc连接

    1.导入orcle驱动的jar包 2.添加配置元件选择 JDBC连接配置 3.添加取样器 JDBCrequest 4.添加观察树,运行 配好密码 OK

  5. mysql可参考的查询

    获取批量修改列为大写SQL脚本 1 SELECT 2 concat( 'alter table ', TABLE_NAME, ' change column ', COLUMN_NAME, ' ', ...

  6. Python笔记(2)——列表一:列表简介(Python编程:从入门到实践)

    一.列表是什么 列表:由一系列按特定顺序排列的元素组成(列表是有序集合). 表示:用方括号[]来表示,并用逗号来分隔其中的元素. 访问:访问列表元素,可指出列表的名称,再指出元素的索引,并将其放在方括 ...

  7. EurekaServer高可用搭建

    生产环境中需要搭建集群达到高可用.eurekaServer每个实例可以注册到其他一个或多个eurekaServer实例中达到高可用.配置比较简单 比如: application-master.prop ...

  8. pytesseract文字识别

    import pytesseract from PIL import Image im=Image.open('image.png') print(pytesseract.image_to_strin ...

  9. js 字符串和16进制的互相转换(转)

    字符串转16进制 function strToHexCharCode(str) { if(str === "") return ""; var hexCharC ...

  10. pytest之运行环境

    简介 pytest是Python最流程化的单元测试框架,它具有允许直接使用assert进行断言,而不需要使用self.assert*:可以自动寻找单测文件.类和函数,还可支持执行部分用例:Modula ...