The 2020 ICPC Asia Macau Regional Contest


A - Accelerator

設加速器序列為 \(a_1, a_2, \cdots, a_n\),那么考慮把題目里的式子展開:\(a_n+a_na_{n-1}+a_na_{n-1}a_{n-2}+\cdots + \prod_{i=1}^n a_i\)

我們把它一項項考慮。對於第 \(k\) 項,如果枚舉過所有 \(n!\) 種情況,那就是對下標集合 \(\{1, 2, 3, \cdots, n-1, n\}\) 選出一個長為 \(k\) 的排列 \(a_{p_1}, a_{p_2}, \cdots, a_{p_n}\)。而每個 \(p\) 都有若干次貢獻,但我們最終要求期望,這個東西最終要被除掉,所有可以不考慮。

簡化一下式子,就是:

\[\frac{\sum\limits_{S\subseteq \{1, 2, \cdots, n\}, |S|=k} \prod_{i\in S} a_i k!}{{n\choose k}k!} = \frac{\sum\limits_{S\subseteq \{1, 2, \cdots, n\}, |S|=k} \prod_{i\in S} a_i}{{n\choose k}} \]

分子上的東西實際上就是 \([x^k]\prod_{i=1}^n (1+a_ix)\)。答案就是 \(\forall k\in \{1, 2, \cdots, n\}\) 求個和。分治 FFT 即可,復雜度 \(O(n\log^2 n)\)​。

B - Boring Problem

真搞死我了這個題。特意學習了一下這種題目的一些解法,好像是什么套路?

像這種往后面隨機加字符,出現給定字符串集合的任意一個后停止,問期望長度的,主流做法有兩種:PGF 和 AC 自動機。但是這題有欽定前綴,PGF 很不好處理,而對於 AC 自動機而言就只要跑一遍就行了,因此我們考慮后者。

首先朴素的思想是,對 \(T_{1\sim n}\) 建立 AC 自動機。然后對每個結點構造方程,最后高斯消元,復雜度 \(O(n^3m^3)\),無法通過。考慮把方程的數量降下來。

注意到一個關鍵性質:對於 Trie 圖中每個點,連出的所有非樹邊的 Trie 樹深度都小於當前點。而且這個性質是一般圖跑了一個 DFS 生成樹所不具備的。

對 Trie 樹做樹鏈剖分(任意選擇重兒子),可以發現雖然 Trie 樹是 \(O(nm)\)​​ 的,但由於只有 \(n\)​ 個串,鏈只有 \(n\)​​​ 條。將作為鏈頂的點設為關鍵點,並嘗試用這些關鍵點表出其他的點。

先寫出朴素的方程:\(E(x)= 1+\sum_{c\in \Sigma} E(\textit{next}_{x,c})\times p_c\)​。我們把重兒子 \(y\)​ 移項(記 \(x\to y\)​ 對應字符為 \(c'\)​),得:\(E(y)=\frac{1}{p_c}(E(x) - \sum_{c \in \Sigma, c \ne c'} E(\textit{next}_{x,c})\times p_c - 1)\)​。根據上面的性質,我們自根向下表示,那么對於 \(y\) 而言,\(E(y)\)\(y\) 的父親和兄弟相關。父親以及兄弟中的“根據 fail 指針補上的邊”都是深度淺於 \(y\) 的,都已被表示而可以直接疊加,其他的兄弟必然都是鏈頂可以直接代入。

現在每個點都有一個關於鏈頂的等式,我們選出 \(n\)​ 個葉子,利用葉子的期望等於 0 建立 \(n\) 個方程,\(O(n^3)\)​ 高消即可。最后帶入等式可以得到所有點的期望。

最后把 \(R\) 放 AC 自動機上跑一遍即可,注意特判葉子。復雜度 \(O(n^3+n^2mk+|R|)\)

C - Club Assignment

從這個角度看問題:每次我們欽定一對點 \(u, v\) 不在同一個 club 里。不難發現一定是在所有關系 \((i, j)\) 二元組中找其中若干個 \(w_i\oplus w_j\) 最小的,越多越好,直到找到一個發現關系沖突了為止。之所以要找最小的,是因為如果我們跳過了一些小的,那這些小的就不得不成為答案(參考 MEX)。

再觀察,發現我們只要使這些關系構成一顆樹(最小異或生成樹)即可,原因是我們不必等到出現沖突,也不用管是不是沒有成樹就出現了沖突,答案方案就已經固定。對於一個固定的方案,我們可以通過 01-Trie 求解答案。

而求異或最小生成樹是個套路問題了。每次按某一位(從高位到低位枚舉)分治,然后借助 01-Trie 找到聯立兩個點集的最小邊即可。總復雜度 \(O(n\log^2 w)\)

D - Artifacts

閱讀理解題。幾個實現技巧:

  • getline 讀入整行;
  • std::string 中的 find 函數可以識別類別;
  • sscanf 讀取數字。

F - Fixing Networks

考慮最省頂點的方式,就是構造 \((d+1)\) 個點的完全圖,用以應付一個 department。最后只需要考慮 \(c=1\) 的情況了。

考慮如下構造:將 \(n\) 個點排成環,每個點向兩側相鄰的 \(\lfloor d/2\rfloor\) 個點連邊。如果 \(d\) 為奇數就向對面再連邊。如果 \(n\) 是奇數使得沒有對面的點,那說明無解,因為這樣整張圖的度數和就是奇數了。

注意特判 \(d=0,1\),以及點數不夠用的情況(\(c(d+1)>n\))。

G - Game on Sequence

一開始有一個比較怪的想法,就是每次 push back 后,從后往前暴力按必勝必敗態定理更新,再加一個如果對當前考慮的點不起作用就跳過。但是感覺不好操作也沒啥前途就先棄了。

其實有更優秀的解法:記 \(s_i\)\(i\) 這個位置先手是否必勝。

考慮一個關鍵性質:對於出現超過一次的 \(x\),選取 \(A_i=A_j=x\)\(i<j\) 的一對 \((i,j)\)。討論一下 \(s_j\)

  • 如果 \(s_j = 0\),那么顯然 \(s_i = 1\)
  • 如果 \(s_j = 1\),那么由於 \(j\) 可以到達的點中存在一個 \(s=0\) 的,而 \(i\) 可以到達 \(j\) 可達的所有位置,那么 \(s_i\) 仍然 \(= 0\)

也就是說,如果詢問一個 \(k\),滿足 \(A_k\) 不是最后一次出現的,那么 \(s_k=1\)。如果是最后一次出現的,我們可以暴力維護 dp 去應付這種詢問。對一個點暴力 dp 復雜度是 \(O(\log A)\),每次 push back 要對所有 \(A\) 都做一遍(這里注意順序)。

總復雜度 \(O(nA\log A)\)​。

I - Nim Cheater

根據博弈論基礎知識(SG 定理),Nim 游戲的后手必勝充要條件是,所有石子堆的石子個數異或起來的結果為 \(0\)。那轉化后的題意就是,對於每次修改操作后,選出一個總花費最大的集合,滿足集合中元素的權值異或和為 \(0\)。修改操作有添加一個元素,以及撤銷。

下面記 \(U=2^{14}=16384\)。一個顯然的 dp 是:\(f(u)\) 表示選取的異或和為 \(u\),最大花費和是多少。每當加入一個元素,就可以在 \(O(U)\) 時間內更新 \(f\)

由於只有添加和撤銷操作,不難發現操作構成一棵樹形結構。建樹后跑 DFS,對每個點都計算一邊 dp 數組。直接這樣做是 \(O(U\times n)\) 的時空復雜度,然而空間限制只有 8 MB,無法通過。

題解提供了一個優秀的想法:由於 DFS 的順序並不影響結果,考慮輕重鏈剖分。對於每個點,我們先計算輕兒子,並將 \(f\)​ 數組復制;最后計算重兒子是直接繼承 \(f\)​ 數組。得益於一棵樹上每個點到根的路徑上都只有不超過 \(O(\log n)\)​ 條輕邊,那么一個點實際上只要保留 \(O(U\log n)\)​ 大小的祖先上的信息。

J - Jewel Grab

轉化詢問:對於一個詢問 \(s, k\),找到一個最長的區間 \([s,t]\),滿足區間中出現次數超過一次的元素的,出現次數減一,的和,不超過 \(k\)。然后對於所有區間中出現次數超過一次的元素,找出其中權值最大的求和;對其他的元素直接求和。計算最終結果。

如果“出現次數”、“區間”相關的題目做多了,不難反應到,定義一個 \(\textit{last}_i\) 表示位置 \(i\) 的元素在序列中上一次出現的位置(第一次出現則 \(\textit{last}_i = 0\))。那么上述的 \(t\) 就是最大的一個整數,滿足 \(\sum_{i=s}^t [\textit{last}_i < s] \le k\)

抓住 \(k\le 10\),即 \(k\) 很小這個特點。考慮我們可以暴力找出所有 \(last_i<s\) 的這些 \(i\),具體的,建立線段樹,維護區間 \(\textit{last}\) 的最小值,然后一次線段樹上二分即可找到一個 \(\textit{last}_i < s\) 的最近的 \(i\)。如此往復 \(O(k\log n)\) 可以完成所有這樣位置的搜尋。

然后我們實現統計答案:求出 \([s, t]\) 的權值和,然后減掉出現次數超過一次的,但不是最大的元素的權值。這里要減去的只有 \(O(k)\) 個。

最后修改是非常簡單的事情,復雜度 \(O(mk\log n)\)

K - Candy Ads

沒寫,口胡一下。可以說非常明顯的 2-SAT 了,將時間看做一維,三維空間下相交說明兩者二選一,以及 \(m\) 個額外限制也是 2-SAT 量身定制。

一開始想了一個比較繁瑣的線段樹優化建圖做法,然后發現四百萬乘上 \(\log\)​ 的時間有點卡,就不管了。

結果發現這玩意可以跑 bitset!(事實上這種很多維度的東西都可以想想這個?)考慮最終我們用 bitset 去維護整個 \(O(n^2)\) 大小的鄰接矩陣,然后用 Kosaraju 算法在上面跑。

建圖時就體現 bitset 的優越之處了。我們考慮有,兩者相交,當且僅當 \(x\) 方向相交 \(\land\) \(y\) 方向相交 \(\land\) 時間區間相交。三維的信息我們做三次(或六次)就行了。時間復雜度差不多是 \(O(n^2/w + m)\)

為什么我不寫呢?因為這題空間只有 512 MB,所以要分塊處理,實在有點麻煩,不想寫了。

L - Random Permutation

從排列的角度考慮問題:對於一個排列 \(p\),有多少合法的 \(a\)?顯然是 \(n!\)。而所有 \(n!\) 種排列都對應 \(n!\)\(a\),那么答案就是 \((n!)^2/n^n\)

然而我傻掉了,使用找規律通過了此題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM