鴿子更博了!
如今大學已塵埃落定,終於成功進入清華,不過不在計算機系。還是希望將\(OI\)作為一種愛好,也想找機會參加\(acm\),因此還是會時不時復健一下。這一題是我記憶中攻克最艱難、解題后也最痛快的一題,因此印象深刻。當然我早已忘了具體的步驟,因此最近重做了一遍,也算是對自己的魔鬼訓練吧。
與群論相關的前置知識:
設\(G\)是所有長度為\(n\)的置換構成的群,\(X\)是一些長度為\(n\)的序列構成的集合。如果將\(G\)作用於\(X\),那么:
對於\(x\in X\),稱\(\{y\in X|y=f(x),f\in G\}\)為\(x\)的軌道,記為\(Orbit(x)\),對於\(y\in Orbit(x)\),稱\(y\)為\(x\)的等價類。
對於\(x\in X\),稱\(\{f\in G|x=f(x)\}\)為\(x\)的穩定化子,記為\(SG(x)\)。
對於\(f\in G\),稱\(\{x\in X|x=f(x)\}\)為\(f\)的不動點,記為\(fix(f)\)。
與題意類似,我們定義兩個森林同構,當且僅當可以通過某種一一對應關系,使得一個森林的任意一棵樹都和另一森林對應的樹同構。
設\(cnt_n\)為\(n\)個點的無標號有根樹個數,並令所有樹從\(1\)到\(cnt_n\)標號。
那么令\(S_{n,i}\)表示所有按照題目要求構造的帶標號有根樹中,與\(n\)個點的\(i\)號無標號有根樹同構的那一部分構成的集合。
由於按照題意建立的\(n\)個點的樹共有\((n-1)!\)種,因此$$ans=\frac{1}{(n-1)!k}\sum_{i=1}{cnt_n}|S_{n,i}|^k$$
那么重點關注后半部分,嘗試利用動態規划的方法解題。那么令:
考慮如何轉移。回想判斷無標號有根樹同構的過程:先將根的所有子樹按照一定規則排序,逐一比較即可。那么是否可以先枚舉排序后在最后的子樹,將其刪去遞歸求解,再考慮這棵子樹的貢獻呢?
但是,如果枚舉排在最后的子樹,那么就隱含了條件:對於遞歸的樹,其根的所有子樹的優先級一定在該子樹之前(或者就是該子樹),而子樹的數目眾多,無法比較好的設計狀態。
但這樣的思考並不是毫無意義的。雖然枚舉最后的子樹不太現實,但也許可以退而求其次,對子樹先進行一個“粗略的划分”,而非直接一個個分離。不難想到先根據子樹大小從小到大初步排序,每次刪去大小最大的那一批子樹,對剩余的樹進行遞歸求解,再考慮這些相同大小的子樹的貢獻。那么對遞歸求解的樹的額外要求,就轉變為了根的子樹大小不能超過某個值,不僅狀態大量減少,考慮起來也非常方便。
那么為了方便,我們記\(mxs(S_{n,i})\)表示對於集合\(S_{n,i}\)中的樹,他們根的子樹的最大大小,類似記\(mns(S_{n,i})\)表示最小的。根據上面的想法,可以設計輔助狀態:
則有\(dp_n=tmp_{n,n-1}\)。再考慮狀態的轉移。那么就枚舉大小為\(p\)的根的子樹的數目,分配標號,再將前后部分獨立考慮。前半部分可以遞歸到之前的狀態,但后半部分無法遞歸,需要單獨解決,表示成式子,就是:
因為\(1\)號點顯然是根,所以實際分配的標號只有\(n-1\)個。其中:
表示需要單獨解決的那一部分。之所以大小為\(u*p+1\),是因為我們給着\(u\)棵大小為\(p\)的樹額外加了一個形式上的根,方便考慮問題。那么第一步先考慮標號的分配。
按照常規來講,標號的分配應該是\({u*p\choose p,p,\dots,p}\)種情況,但在此處,由於根的所有子樹之間是沒有順序的(這也是之前進行“粗略的划分”遺留下來的問題),因此如果出現兩棵相同的子樹,它們的地位完全等價,也即即使賦予它們的標號互換,得到的也是同一種結果。但是\({u*p\choose p,p,\dots,p}\)的分配方式顯然將互換前后看作不一樣的。
看來\({u*p\choose p,p,\dots,p}\)並不能適用於所有情況,還需要進行進一步的分類討論。那么我們假設其中某一個\(S_{u*p+1,i}\),其根的子樹可以分為\(m\)類本質不同的,且數目分別為\(a_1,a_2,a_3,\dots,a_m\Big((\sum_{t=1}^ma_t)=u\Big)\),也不妨將\(a\)不降序排序。對於同一類的子樹內部,任意兩棵樹都可以互換標號,因此分配給這一類的\(a_t\)組標號彼此是無序的,需要將分配標號方案數乘以\(\frac{1}{a_t!}\)。因此對這一情況,分配的方法數應該為:
初步解決分配標號的問題后,我們再考慮下一步操作。此時只要將\(u\)棵子樹內部的標號都看作是\(1,2,\dots,p\)即可,此時可以去掉形式上的根,將其轉化為\(u\)棵樹的森林。根據之前的定義,我們可以將全體大小為\(p\)的無標號有根樹編號為\(1,2,\dots,cnt_p\)。對於某一個森林,將其每一棵樹對應到這棵樹所屬類別的編號,我們可以將該森林與一個無序可重集合\(\widetilde x\)對應。將所有\(\widetilde x\)組成的集合記作\(\widetilde X\)。
則\(\widetilde x\)滿足兩個性質:恰好包含\(u\)個數,且每個數都在\(1\)到\(cnt_p\)之間。也可以將\(a_t\)的概念從\(S_{u*p+1,i}\)遷移到\(\widetilde x\)上。不妨記\(\omega_{\widetilde x}\)為屬於\(\widetilde x\)對應森林的帶標號森林的數目的\(k\)次冪,那么\(f_{p,u}\)可以表示為:
因為在分配完標號以后,樹的同構就轉化為了森林的同構。
然而,由於\(\widetilde x\)是無序可重集合,這非常不利於枚舉,因此直接進行計算也非常麻煩。希望能將其轉化為有序可重集合(即一個長度為\(u\)的序列)再進一步解決問題。
那么設\(x\)是一個長度為\(u\)的序列,且每一個數都在\(1\)到\(cnt_p\)之間。將所有這樣的\(x\)的集合記做\(X\)。如果\(x\)無序化后能和某一個\(\widetilde x\)相同,我們稱\(x\)對應到\(\widetilde x\)。
由於\(\widetilde x\)是一個可重的集合,因此對應到\(\widetilde x\)的\(x\)的數目是變化的,不能直接枚舉\(x\)。想要利用\(X\)得到一個和\((*)\)相類似的等式,還需要借助置換群。
為了表達方便,用前置知識中的術語來表達。設\(G\)是所有長度為\(u\)的置換構成的群,將\(G\)作用於\(X\)。
那么對於一個\(Orbit(x)\),所有在這一集合內的\(y\)都對應到相同的\(\widetilde x\),可以用\(Orbit(x)\)來代替\(\widetilde x\)。將\(a_t\)、\(\omega\)的概念遷移到\(x\)上,我們可以得到與\((*)\)類似的式子:
不難發現\(|Orbit(x)|=\frac{u!}{\prod_{t=1}^ma_t!}\)。此時有一個難點,就是\(\omega_x\)的計算。先嘗試將所有\(a\)相同的\(x\)發在一起計算(此時\(\bigg(\prod_{t=1}^m\frac{1}{a_t!^k}\bigg)\)和\(|Orbit(x)|\)是相同的)。也就是說,此時的森林要求有\(m\)種不同的樹,第\(i\)種\(a_i\)棵。首先考慮\(m=1\)的情況,也就是需要\(u\)棵同構的樹,不難發現這就等同於:
看上去似乎並未計算過這個式子,為了計算可能需要修改狀態。那么先擱置一邊,考慮\(m>1\)的情況,我們能否直接用下面的式子:
計算呢?不可行,因為這並不能排除不同的兩組得到同一類樹的情況,同時也沒有考慮組與組的數目相同時地位等價的問題。
但這樣的思考並不是毫無意義的。不難發現,如果組與組之間默認為地位不等,且不同的組可以使用相同的一類樹,那么\((**)\)就是正確的。
最關鍵的一點是,這兩個條件似乎與某一置換下的不動點有異曲同工之妙。我們考慮\(f\in G\),則\(fix(f)\)就是\(f\)的不動點集合。\(f\)是由若干個置換環組成的,設有\(m'\)個置換環,並設置換環的大小分別為\(a'_1,a'_2,\dots,a'_{m'}\)。可以發現,如果\(x\)是\(f\)的不動點,那么有與之前的\(a\)類似的性質,同一置換環內的位置上,樹的種類必須相同。但是,由於置換環本身位置不同,每個置換環就是地位不等的(這也是有序序列的一個好處)。並且,由於我們只要求其為不動點即可,並不需要每個置換環的樹種類各不相同,這就完美的符合我們之前的兩個條件。
因此我們就可以利用\((**)\)了,也就是說:
不過還有一個問題沒有解決:怎么求\(\sum_{i=1}^{cnt_p}|S_{p,i}|^{a'_t*k}\)?它的形式和\(dp_p\)相似,但是指數增加了\(a'_t\)倍。必須先進一步擴張狀態才能解決這個問題。
那么增加一個指標\(j\),表示指標擴張的倍數。即:
相應修改轉移方程:
則:
注意\(\omega_x\)也是和\(j\)相關的。
首先考慮一下狀態數量問題,可以發現由於\(a'_t\leq \frac{n}{p}\),因此這兩維的乘積不會超過全局的\(n\),因此只有\(\sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloor=O(n\log n)\)種可能。
還有一個問題是,我們並不只是簡單的求\(\sum_{x\in X}\omega_x\),而是有一個\(\Big(\prod_{t=1}^m\frac{1}{a_t!^{j*k}}\Big)*\frac{1}{|Orbit(x)|}\)的系數,不能這樣直接交換求和順序。
那要通過什么方式轉化呢?我們設置換\(f\)的某個權值為\(w_f\),那么有如下等式:
只是交換了求和順序,顯然成立。這個等式的左邊和\(\sum_{x\in X}\bigg(\prod_{t=1}^m\frac{1}{a_t!^{j*k}}\bigg)*\frac{\omega _x}{|Orbit(x)|}\)相似,右邊和\(\sum_{x\in fix(f)}\omega_x\)相似,嘗試利用這個等式來對目標進行轉化。
如果能找到某種權重函數\(w\),使得等式:
成立,其中\(C\)是一個常數,那么就有:
由於后方的連乘只和置換環大小情況有關,那么自然也希望權重函數也之和置換環大小有關,而且最好也是連乘形式,即:
如果可行,那么可以繼續轉化\((***)\)式:
則每個置換的結果都只和其置換環分解的大小分布情況有關,可以換一種求和方式,令\(h_i={\widetilde w}_{i}*dp_{p,i*j}\),枚舉置換環的大小分布,並分配標號:
似乎轉化為了熟悉的式子。設生成函數\(H(x)=\sum_{i>0}\frac{h_i}{i}x^i\),那么前面的式子就轉化為:
好的!也就是說,我們現在有:
唯一的問題就是計算權重函數\(\widetilde w\)了。回顧一下,我們是希望滿足這個等式:
展開\(|Orbit(x)|\),即:
對於\(x\),它的穩定化子就是滿足僅在相同種類樹之間進行置換的集合,就是說,只能在同種樹內部進行置換環的拆解。那么模仿之前對置換環的枚舉方法,換一種方式計算等式左邊的值,只是換成了在每一類樹內部:
同之前,設\(W(x)=\sum_{i>0}\frac{{\widetilde w}_i}{i}x^i\),那么上方等式繼續轉化:
帶回原等式,即為:
消去\(\prod_{t=1}^{m}a_t!\):
顯然我們令\(C=u!\),那么有\([x^i]e^{W(x)}=\frac{1}{i!^{j*k}}\),\(e^{W(x)}\)就是一個已知的多項式。通過\(W(x)=\ln e^{W(x)}\)就可以求解出\(\widetilde w\)了。
回顧一下過程,可以計算出復雜度是\(O(n^2\log n)\)。由於多項式\(\ln\)和\(\exp\)不是瓶頸,可以用簡潔的\(O(n^2)\)算法來計算。