【KFC】JZ408 Koufu Contest 3 题解

甲 解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} \]

没了(

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章