【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} \]

沒了(

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