IOI 2021 國家集訓隊作業:試題泛做記錄


廣告位,宣傳水題 https://ioihw20.duck-ac.cn/problem/301

截至 \(\text{2020.12.7}\),已完成 \(81/150\)(看題解的算不清楚就不寫了)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(173\)\(\text{Equal Numbers}\)\(\text{2020.10.12}\),自己做出)

題目大意:

給定正整數可重集 \(a_{1\ldots n}\),一次操作定義為:選擇 \(i\in [1,n]\),令 \(a_i\) 乘上一個任意的正整數,對於所有 \(k\in [0,n]\),求出 \(k\) 次操作后可重集中至少有多少種不同的數。

\(n\leq 3\times 10^5,\ \ a_i\leq 10^6\)


題解:

如果一次操作后 \(a_i\) 沒有變成原始集合中的某個數,那么顯然我們可以令它變為原始集合中所有數的公倍數 \(S\),這樣以后其他數也可以變成這個公倍數,這一定不劣於變成其他數。

於是我們有兩種選擇:

  1. 將某些數變成 \(S\),那么我們自然是選擇出現次數最少的若干個數,將它們統一變成 \(S\)

  2. 不將任何數變成 \(S\),那么我們只能對那些存在一個真倍數在原始集合中的數進行操作,選擇它們中出現次數最少的若干個數變成它們的某個倍數。

所以我們通過兩個數組記錄所有出現過的數的出現次數和作為其他數真因子出現的數的出現次數(直接利用倍數枚舉可以找出這些數),當 \(k\)\(0\) 變到 \(n\) 時對每個數組維護一個指針表示當前的 \(k\) 足以將多少個數全部操作一遍。

時間復雜度為 \(O(A\log A+n)\),其中 \(A\) 為值域大小。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(177\)\(\text{Outer space invaders}\)\(\text{2020.10.12}\),瞄了眼題解)

題目大意:

\(n\) 個外星人,第 \(i\) 個外星人有權值 \(d_i\),需要在 \([a_i,b_i]\) 中某個時間被消滅,一次功率為 \(P\) 的攻擊只能消滅權值不超過 \(P\) 的外星人,問消滅所有外星人的最小功率總和。

共詢問 \(T\) 組數據。

\(T,n\leq 300,\ \ a_i,b_i,d_i\leq 10^4,\ \ \sum n^3\leq 2.5\times 10^8\)


題解:

查這題的時候順便看到了正解用到了區間 DP,之后就不難想了。

\(dp(i,j)\) 表示消滅所有包含於 \([i,j]\) 的外星人的最小功率,我們找到這些外星人中權值最大的,枚舉消滅它的時間 \(t\),那么與此同時所有包含 \(t\) 的外星人也會被同時消滅,只要分別遞歸計算 \(dp(i,t-1)\)\(dp(t+1,j)\) 即可。

注意區間要先離散化。

時間復雜度為 \(O(\sum n^3)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(209\)\(\text{Intrinsic Interval}\)\(\text{2020.10.12}\),模擬賽原題)

題目大意:

給定 \(1,\ldots,n\) 的排列 \(\pi_{1\ldots n}\),定義區間 \([l,r]\) 為連續段當且僅當排列中 \([l,r]\) 當中所有數排序后是公差為 \(1\) 的等差數列,現有 \(m\) 組詢問,每次詢問包含 \([l,r]\) 的最短連續段,可以證明這是唯一的。

\(n,m\leq 10^5\)


題解:

是原題,直接搬運我以前寫的題解了。

結論 1:設 \(ans(l,r)\) 表示詢問區間 \([l,r]\) 的答案,則 \(ans(l,r)=\bigcup\limits_{i=l}^{r-1}ans(i,i+1)\)

注意要特判 \(l=r\)

這個結論不證了,因為可以腦補,而且證起來又有點麻煩。

所以我們求出 \(ans(i,i+1)\) 即可。

結論 2:設 \(L_i,R_i\) 分別表示以 \(i\) 為右/左端點的連續區間的最遠左/右端點,則 \(ans(i,i+1)=[\max(j|j\leq i,L_j\ge i+1),\min(j|j\ge i+1,R_j\leq i)]\)

道理和結論 1 差不多,也不證了。

於是問題又轉化為求 \(L_i,R_i\),求完以后上面那個東西二分一下 \(j\),用 ST 表判定即可。

這個東西就要上線段樹了,從左到右掃一遍 \(r\),對於每一個 \(r\),計算最左邊的 \(l\),即為 \(L_r\),再反着做一遍,可以類似得到 \(R_l\),這里只講前面一個了。

考慮 \([l,r]\) 是連續區間,等價於 \((\max(p_i|i\in [l,r])-\min(p_i|i\in [l,r]))-(r-l)=0\),當 \(r\) 固定時它是關於 \(l\) 的函數,設為 \(f(l)\),用線段樹維護 \(f(l)\),考慮從 \(r\) 變成 \(r+1\)\(f(l)\) 的變化。

考慮每一項的變化即可,\(r\) 對於每個 \(f(l)\) 來說都增加了 \(1\),所以先將整個左邊區間加 \(1\)

\(\max\)\(\min\) 類似,這里以 \(\max\) 為例。

用一個單調棧維護遞減當前 \(p_i\),則如果 \(p_{r+1}>p_{top}\),那么要彈棧,並且 \(p_{top}\)\(p_{top}\) 前一個元素 \(+1\) 這一段的最大值變成了 \(p_{r+1}\),原本這一段的最大值是 \(p_{top}\),所以相當於整體加上一個 \(p_{r+1}-p_{top}\)

有很多對稱的東西,類似處理即可。

時間復雜度 \(O(n\log n+m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(297\)\(\text{Surveillance}\)\(\text{2020.10.13}\),自己做出)

題目大意:

給定若干環上區間,選擇最少的區間覆蓋整個環,或報告無解。

環長為 \(n\),區間數為 \(k\)

\(n,k\leq 10^6\)


題解:

國旗計划弱化版。

首先復制為兩倍破環為鏈,然后直接倍增,令 \(f(i,j)\) 表示從 \(i\) 開始覆蓋 \(2^j\) 個區間最右能到多少,其中 \(f(i,0)\) 可以從左到右掃一遍,求左端點在 \([1,i]\) 的區間右端點的最大值。

然后從每個左端點倍增跳一下就可以了。

時間復雜度為 \(O((n+k)\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(238\)\(\text{Kebab House}\)\(\text{2020.10.13}\),自己做出)

題目大意:

你要依次制作 \(n\) 個烤肉串,第 \(i\) 個會花費 \(q_i\) 的時間,每個單位時間你可以走神或不走神,但兩次相鄰走神必須間隔大於 \(t\) 單位時間,烤第 \(i\) 個串的時候至少有 \(x_i\) 個單位時間沒有走神,問走神的方案數,對 \(10^9+7\) 取模。

\(n\leq 1000,\ \ k\leq 100,\ \ q_i\leq 250\)


題解:

\(dp(i,j)\) 表示烤完前 \(i\) 個串,最后一次走神是第 \(i\) 串烤完前的倒數第 \(j\) 單位時間的方案數,特別地,\(dp(i,t)\) 表示最后 \(t\) 單位時間內都沒有走神的方案數。

那么枚舉一個 \(k\),從 \(dp(i-1,k)\) 轉移到 \(dp(i,j)\),轉移系數應當是對於第 \(i\) 個串中間的某個區間,走神次數不超過 \(q_i-x_i-1\)(或一些類似的東西)的方案數。

所以我們再來一次 DP,設 \(f(i,j,k)\) 表示長為 \(i\) 的區間,走神 \(j\) 次,最后一次走神是倒數第 \(k\) 單位時間(對於 \(k=t\) 同樣特殊定義),如果 \(0<k<t\) 那么就是 \(f(i-1,j,k-1)\),否則枚舉一下上次走神是什么時候。

時間復雜度為 \(O(nt^2+Q^2t)\),其中 \(Q\)\(q_i\) 的值域。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(123\)\(\text{Gem Island}\)\(\text{2020.10.13}\),看了題解)

題目大意:

島上有 \(n\) 個居民,每個居民初始有一個寶石,每一天都會等概率選擇一個寶石分裂成兩個,問 \(d\) 天后寶石數量前 \(r\) 多的人的寶石數量和期望是多少。

\(n,d,r\leq 500\)


題解:

題目中這個分配方式,相當於將 \(d\) 個寶石分給 \(n\) 個人,最后每人多給一個。

我們設 \(f(i,j),g(i,j)\) 分別表示 \(j\) 個寶石分給 \(i\) 個人時,人帶標號的方案數和前 \(r\) 大值之和,那么答案就是 \(\dfrac{g(n,d)}{f(n,d)}+r\)(最后加上每個人多給的一個寶石)。

枚舉有多少人得到了至少一個寶石,可以得到轉移方程:

\[f(i,j)=\sum\limits_{k=0}^{\min(i,j)} \binom i kf(k,j-k) \]

表示有 \(k\) 個人得到寶石,每人先分一個,剩余 \(j-k\) 個再遞歸計算。

同理有 \(g(i,j)\) 的轉移:

\[g(i,j)=\sum\limits_{k=0}^{\min(i,j)} \binom i k(g(k,j-k)+\min(k,r)f(k,j-k)) \]

后面一項指的是每個人先分得的一個寶石的貢獻。

利用 \(\text{long double}\) 計算,我也不知道為什么精度怎么算,反正過了。

時間復雜度為 \(O(n^3)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(121\)\(\text{Bipartite Blanket}\)\(\text{2020.10.14}\),自己做出)

題目大意:

給定左邊 \(n\) 個點右邊 \(m\) 個點的點帶權二分圖,求滿足下列條件的點集數量:

  • 點權和不小於 \(t\)

  • 是某個匹配的子集。

\(n,m\leq 20,\ \ t\leq 4\times 10^8\)


題解:

主要結論:設左右部點分別為 \(L,R\),那么 \(S=A\cup B\ \ (A\subseteq L,\ B\subseteq R)\) 是某個匹配的子集當且僅當 \(A\) 是某個匹配的子集且 \(B\) 是某個匹配的子集。

具體證明可以把 \(A,B\) 所屬的匹配畫出來,在里面找增廣路來證明,不過這個屬於比較直覺的東西,就不具體說了。

我們只需要求出左右兩部所有是某個匹配子集的點集求出來,再雙指針一下就可以得到答案。

詢問一個點集 \(S\) 是不是某個匹配的子集,相當於在它這一部只保留 \(S\) 時最大匹配為 \(|S|\),可以簡單地利用 Hall 定理判定。

首先求出 \(f(S)\) 表示 \(|\bigcup\limits_{i\in S}N(i)|\ge|S|\) 是否成立,然后對它做一次 FWT 就可以得到每個點集是不是一個匹配的子集。

時間復雜度為 \(O(n2^n+m2^m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(293\)\(\text{Weather Report}\)\(\text{2020.10.14}\),自己做出)

題目大意:

對接下來 \(n\) 天進行天氣預報,每天的天氣有四種可能,每種天氣出現概率給定且不隨天數變化。

現在要將 \(4^n\) 種可能的天氣序列分別映射到一個 \(01\) 串,使得不存在兩個映射得到的 \(01\) 串為前綴關系,求 \(01\) 串的最小期望長度。

\(n\leq 20\)


題解:

對於所有可能的天氣序列對應的概率求一次 Huffman 樹即可。

天氣序列的數量有 \(4^n\) 種,無法一一處理,但是注意到一種天氣序列出現的概率只和每種天氣出現次數有關,所以不同的概率只有 \(\binom {n+3}{3}\) 種。

於是問題轉化成了有 \(m\) 種元素,第 \(i\) 種有 \(a_i\) 個的 Huffman 樹,只需要在優先隊列的每個元素維護一個重復數 \(a_i\),對於取出的堆頂,如果重復數 \(a_i\) 超過了 \(1\),那么先兩兩配對為 \(\lfloor\dfrac{a_i}{2}\rfloor\) 對,若多出一個則將其與堆中的下一個元素匹配。

時間復雜度不知道,但過了。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(146\)\(\text{Tile Cutting}\)\(\text{2020.10.15}\),自己做出)

題目大意:

在一個長寬為任意正整數的矩形上的四條邊各選一個整點,順次連接然后切割下來形成一個平行四邊形,設面積為 \(S\) 的平行四邊形有 \(c_S\) 種切割方法(旋轉翻折不等價),有 \(q\) 次詢問,每次詢問 \(c_l,\ldots,c_r\) 的最大值和對應的 \(S\)

\(q\leq 500,\ \ l,r\leq 5\times 10^5\)


題解:

顯然對邊選擇的頂點連線過矩形中心。

設矩形尺寸為 \(a\times b\),割出來的其中一個小三角形尺寸為 \(c\times d\),通過簡單計算可以知道 \(S=ad+bc-2cd\),幾何的理解就是 \(S=d(a-c)+c(b-d)\),即兩個小矩形的面積和。

所以 \(c_S\) 就是將 \(S\) 分成兩個數之和,每個數再分成兩個數之積的方案數,那么 \(c_S=\sum\limits_{i=1}^{S-1}\sigma_0(i)\sigma_0(S-i)\),一次多項式乘法即可求出,打個表可以發現 \(c_{5\times 10^5}\) 遠遠不到 \(10^9\),因此單模數的 NTT 就已經足夠。

最后再套個 ST 表求最大值。

時間復雜度為 \(O(L\log L+Q)\),其中 \(L\)\(l,r\) 值域。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(146\)\(\text{King’s Inspection}\)\(\text{2020.10.15}\),自己做出)

題目大意:

\(n\) 個點 \(n+k\) 條邊的有向圖中求解一條哈密爾頓回路,或報告無解。

\(n\leq 10^5,\ \ k\leq 20\)


題解:

設點 \(i\) 的入度為 \(in_i\),那么 \(\sum\limits_{i=1}^n in_i=n+k\),如果存在 \(in_i=0\) 那么顯然無解,否則 \(in_i\ge 1\),那么至多有 \(k\) 個點滿足 \(in_i>1\)

對於 \(in_i=1\) 的點,前驅確定,可以直接縮掉,只保留 \(in_i>1\) 的點,每個點的出邊縮成從它出發不斷走到 \(in_i=1\) 的點,這條鏈末尾的那個點的出邊。

在新圖上狀壓 DP,每個點記錄前驅以輸出方案。

時間復雜度為 \(O(n+2^k)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(294\)\(\text{Gangsters in Central City}\)\(\text{2020.10.15}\),自己做出)

題目大意:

給定 \(n\) 個點的根結點為 \(1\) 的有根樹,接下來發生 \(q\) 個操作,每個操作形如有一個葉結點被敵人占領或有一個葉結點不再被敵人占領。

你需要選擇一些樹邊切斷,使得根結點到所有被敵人占領的點不連通,最小化割去的邊數,同時在最小化割去邊數的情況下最小化未被敵人占領但與根結點不連通的葉結點數量。

每次操作后你需要輸出最小割去邊數和最小的未被敵人占領但與根結點不連通的葉結點數量。

\(n,q\leq 10^5\)


題解:

前一問的答案是顯然的,根結點的每個子樹中最多割一條邊,只要看這個子樹里有沒有被敵人占領的點即可。

而為了使后一問的答案盡可能小,對於根結點每個存在被敵人占領的點的子樹,被切斷的一定是所有被占領點的 \(\text{LCA}\) 到父親的邊。

一些點的 \(\text{LCA}\) 等於其中 DFS 序最大和最小點的 \(\text{LCA}\),我們用一個 set 維護每個子樹中所有點的 DFS 序,即可實現插入,刪除,查詢 \(\text{LCA}\)

時間復雜度為 \(O((n+q)\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(255\)\(\text{Money for Nothing}\)\(\text{2020.10.15}\),自己做出)

題目大意:

給定 \(n\) 個紅點 \((a_i,b_i)\)\(m\) 個藍點 \((c_i,d_i)\),求 \((a_i-c_j)\times (b_i-d_j)\ \ (a_i\ge c_j,\ b_i\ge d_j)\) 的最大值。

\(n,m\leq 5\times 10^5\)


題解:

第一個單調性:如果一個紅點在另一個紅點左下方,那么可以扔掉。

同樣的單調性:如果一個藍點在另一個藍點右上方,那么可以扔掉。

所以紅點集合和藍點集合分別可以化簡成一個 \(y\) 坐標隨 \(x\) 坐標增加而單調減的點集,設紅點對應的此集合從左到右為 \(c_1,\ldots,c_s\),藍點對應的此集合從左到右為 \(d_1,\ldots,d_t\)

第二個單調性:對於每個紅點 \(i\),設 \(f_i\) 表示使得 \((a_i-c_j)\times (b_j-d_j)\) 最小的 \(j\),那么 \(f_i\)\(i\) 單調不下降。

為證明這個結論,我們可以先證明一個基本結論:如果 \(x<y,\ \ u<v\),且 \((a_x-c_v)\times (b_x-d_v)> (a_x-c_u)\times (b_x-d_u)\),那么可以推出 \((a_y-c_v)\times (b_y-d_v)> (a_y-c_u)\times (b_y-d_u)\)

這是因為前者等價於 \(b_x(c_u-c_v)+a_x(d_u-d_v)<c_ud_u-c_vd_v\),而左邊大於 \(b_y(c_u-c_v)+a_y(d_u-d_v)\),這又等價於我們要證明的的結論。

於是反復利用這個基本結論即可證明上述單調性。

所以最后用分治 DP 的處理方法做一下就可以了。

注意首先把 \(c_i\) 中所有不在任何 \(d_j\) 右上角的去掉,否則分治的時候不知道怎么縮小范圍。

時間復雜度為 \(O((n+m)\log(n+m))\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(122\)\(\text{Intellectual Property}\)\(\text{2020.10.16}\),自己做出)

題目大意:

給定 \(n\)\(9\times 9\) 數獨謎題,其中某些地方沒有填數,判斷任意兩個謎題是否本質相同,如果本質相同還需要輸出轉換的方法。

具體的得到等價謎題的操作包括:交換含有相同 \(3\times 3\) 方塊的行或列,整體交換這樣的三個行或列,交換謎題中兩種數字,以及沿左上右下對角線翻轉。

\(n\leq 20\)


題解:

有個顯然的做法,暴搜每個數獨可以操作得到的所有數獨,哈希之后放到一個 map 里,查詢時直接用一個數獨在另一個數獨的 map 里查詢。

但是一個數獨的等價數獨有 \(2\times 6^8\times 9!\) 種,考慮減少這個個數。

首先,\(9!\) 很容易去掉,交換兩種數字的操作可以放到最后進行,我們只需要設計一種對數字相對大小不敏感的哈希函數即可。

而剩下的 \(2\times 6^8\) 我們可以拆成 \(6^4\)\(2\times 6^4\),也就是放在 map 里的等價數獨是只改變了行而沒有改變列的,查詢的時候相反,我們枚舉另一個數獨改變列的所有等價數獨,都在 map 里查一遍,這樣就可以通過本題了。

代碼實現上有很多細節,比較難寫。

時間復雜度為 \(O(Mn^2\log M)\),其中 \(M\)\(6^4\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(170\)\(\text{String Theory}\)\(\text{2020.10.16}\),自己做出)

題目大意:

一個 \(k\) 級引用串的左右兩端是 \(k\) 個引號,中間的部分是若干個 \(k-1\) 級引用和不包含引號的字符串的連接。

給定一個長度為 \(n\) 的引號串(給出每一段引號的個數 \(a_{1\ldots n}\)),求出它最多是幾級引號串,或報告無解。

\(n,a_i\leq 100\)


題解:

首先我們將每一段引號拼在一起,變成連續 \(\sum\limits_{i=1}^n a_i\) 個引號。

接下來 DP,設 \(dp(i,l,r,k)\) 表示前 \(i\) 個引號匹配完成后,剩下左端未匹配的引號依次是 \(l,l+1,\ldots,r\) 級引號,最后的 \(k\) 是一個標記變量,值為 \(0\)\(1\),表示當前正在匹配的引號串的內部是否已經有一個一級引號(只有有了一級引號才能形成最終的引號串)。

轉移大概是從 \(dp(i-l+1,l-1,r)\)\(dp(i-l,l+1,r)\) 轉移到 \(dp(i,l,r)\),最后一維分一些情況討論一下轉移即可,注意只有最后才能將所有引號封口。

時間復雜度為 \(O(n^3A)\),其中 \(A\)\(a_i\) 的最大值。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(134\)\(\text{J}\)\(\text{2020.10.16}\),自己做出)

題目大意:

給定一個包含加,減,乘,平方,負號,折疊(求一個向量各分量之和)運算的包含 \(n\) 維向量和標量的長度為 \(|S|\) 的算式 \(S\)(標量加減向量時看作各分量一致的向量,向量乘法為對應分量相乘),保證次數不超過 \(10\),求值,對 \(10^9\) 取模。

對於 \(S\) 有如下約定:其中所有出現的向量只包括一個事先給定的 \(X\),標量為一個數或者 \(n\),運算優先級為從右到左,但可能有括號。

\(n,|S|\leq 10^5\)


題解:

只要求出 \(X\) 各分量的 \(k\) 次方和(\(k\leq 10\)),就可以快速求出折疊操作的值,對於其他運算其實都看成多項式的加減乘即可。

然后遞歸求值就做完了。

時間復雜度為 \(O((n+|S|)k)\),其中 \(k=10\) 為最大次數。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(175\)\(\text{Ice Igloos}\)\(\text{2020.10.16}\),自己做出)

題目大意:

給定 \(n\) 個圓心為坐標在 \([1,500]\) 中的整點,半徑小於 \(1\) 的圓,任意兩圓無公共點,接下來 \(q\) 次詢問一條直線與多少圓相交(不存在相切情況)。

\(n,q\leq 10^5\)


題解:

暴力實現,如果斜率絕對值小於 \(1\) 就枚舉圓心的橫坐標,否則就枚舉圓心的縱坐標,容易發現在這種方式下圓心的另一維坐標只會在直線的上下 \(2\) 單位范圍內(可以把垂直或水平距離放成 \(\sqrt 2\))。

時間復雜度為 \(O(n+qX)\),其中 \(X\) 為坐標范圍大小。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(153\)\(\text{Fygon 2.0}\)\(\text{2020.10.17}\),自己做出)

題目大意:

給定 \(m\) 層嵌套的 for 循環語句,每個循環包含循環變量和上下界,其中上下界是外層變量或 \(1\)\(n\),求關於 \(n\) 的漸進復雜度和最高次項系數(常數)。

\(m\leq 20\)


題解:

用一個 \(m\) 元組表示每一層循環變量的取值,容易發現一個 \(m\) 元組能否取到只和每個數的相對大小關系有關。

所以我們從下界到循環變量連一條有向邊,從循環變量到上界連一條有向邊,將強連通分量縮點,剩下的圖中的點數就是復雜度(次數),而對這張圖進行拓撲序計數,如果有 \(T\) 種拓撲序就有 \(T\) 種相對關系,每一種相對關系都是 \(\binom {n+m-1}{m}\)(其中 \(m\) 是復雜度次數)種,所以常數就是 \(\dfrac{T}{m!}\)

時間復雜度為 \(O(m\times 2^m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(278\)\(\text{Journey from Petersburg to Moscow}\)\(\text{2020.10.17}\),看了題解)

題目大意:

給定 \(n\) 個點 \(m\) 條邊的無向帶權圖,定義一條路徑長度為前 \(k\) 長邊權的和(如果邊數不到 \(k\),路徑長就等於邊權和),求 \(1\)\(n\) 最短路。

\(n,m,k\leq 3000\)


題解:

第一種選擇是最短路(這是為了計算邊數可能不到 \(k\) 的情況)。

其他的選擇,我們枚舉哪條是第 \(k\) 大邊,設其邊權為 \(W\),將所有邊權更大的邊的邊權減少 \(W\) 后求最短路(邊權更小的邊的邊權直接設為 \(0\)),用 \(dis_n+kW\) 更新答案,可以發現這等價於只選了不小於 \(W\) 的邊計算貢獻。

時間復雜度為 \(O(nm\log m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(147\)\(\text{Traffic Blights}\)\(\text{2020.10.17}\),模擬賽原題)

題目大意:

\(n\) 個紅綠燈,第 \(i\) 個燈在位置 \(x_i\),為 \(r_i\) 秒紅燈和 \(g_i\) 秒綠燈交替變換(從紅燈開始),現在隨機選擇一個時間點從位置 \(0\) 開始以 \(1\) 的速度前進,求每個燈是第一個遇到的紅燈的概率以及一個紅燈都沒遇到的概率。

\(n\leq 500,\ \ r_i+g_i\leq 100\)


題解:

\(s_i=r_i+g_i\)

如果所有 \(s_i\) 兩兩互質,那么每個燈都獨立,我們只需要算出之前的燈都綠的概率乘上這個燈紅的概率即可算出這個燈是第一個紅燈的概率。

如果有一些 \(s_i\) 不互質,但是不互質的 \(s_i\) 都相等,那么也差不多,我們考慮某個燈時,所有 \(s_i\) 與它不相等的燈和它獨立,而考慮 \(s_i\) 相等的燈中,可以發現每盞燈的紅燈時間都覆蓋了出發時間 \(\bmod s_i\) 意義下的一段區間,我們暴力修改和查詢區間中 \(1\) 的個數就可以計算這些燈的貢獻了。

如果情況更加復雜,我們考慮簡化它,取一個包含足夠素因子的數 \(M\),使得所有 \(\dfrac{s_i}{\gcd(s_i,M)}\) 兩兩要么互質,要么為倍數關系,那我們就可以枚舉出發時間 \(\bmod M\) 的余數,然后用上面的方法計算了(如果不互質的 \(s_i\) 都為倍數關系,那么我們只需要將短的補齊,覆蓋長的 \(s_i\) 中的若干段時間即可)。

\(M=2^3\times 3^2\times 5\times 7=2520\) 即可做到這一點,因為此時 \(s_i\) 除去與 \(M\) 的最大公約數后不會有超過一個素因子。

時間復雜度為 \(O(MSn)\),其中 \(M=2520\)\(S\)\(r_i+g_i\) 的最大值。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(202\)\(\text{Clock Breaking}\)\(\text{2020.10.17}\),自己做出)

題目大意:

給定顯示時分的電子鍾連續 \(n\) 分鍾的示數,每個格子有三種可能狀態:正常,一直亮或一直滅,你需要求出每個格子的狀態,或報告這個格子的狀態無法確定,或報告無解。

電子鍾的尺寸是 \(7\times 21\),數字顯示見題面。

\(n\leq 100\)


題解:

首先看輸入給定的示數中每個格子有沒有亮或者暗過,如果又亮過又暗過,那么這個格子一定正常。

然后再枚舉起始時間,根據正常的格子檢驗這個時間是否合法,如果合法,再通過這個事件倒過去檢驗在輸入中一直亮或一直滅的格子究竟是壞了還是可能正常顯示。

注意,如果有多個可能的起始時間,那么對於某個格子,只要對於其中一個時間,該格子是無法確定的,那么最終答案中該格子就無法確定。

時間復雜度為 \(O(TMn)\),其中 \(T=24\times 60=1440\) 為一天的分鍾數,\(M=7\times 21=147\) 為電子鍾尺寸。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(259\)\(\text{Jazz Journey}\)\(\text{2020.10.17}\),自己做出)

題目大意:

有一個持續 \(d\) 天的在 \(n\) 座城市中旅行的計划,第 \(i\ (i<d)\) 天要從城市 \(a_i\) 乘機直達城市 \(a_{i+1}\)

\(m\) 種機票,分成單程和往返兩種,往返機票只有先按照一個方向經過后才能按反方向經過(第一次經過的方向給定),也可以當成單程票用,每種機票有一定費用,求完成旅行的最小開銷。

\(n,m,d\leq 3\times 10^5\)


題解:

顯然每對城市之間的旅行安排是獨立的,我們首先將每天的計划按照出發和到達地點相同的分為一類,下面就討論兩個地點 \(a,b\) 之間的旅行安排。

設從 \(a\) 飛到 \(b\) 的一天記為 \(0\),從 \(b\) 飛到 \(a\) 的一天記為 \(1\)\(a\to b,\ \ b\to a\) 的單程票價分別為 \(A,B\),往返票價分別為 \(C,D\),為了避免過多分類討論,令 \(A=min(A,C),B=min(B,D)\),然后再令 \(C=min(C,A+B),D=min(D,A+B)\)

我們找到 \(C,D\) 中較小的一個,顯然使用這種票是最為划算的(比單程和另一種往返都划算),所以要盡可能多用,而這也就是把 \(0,1\) 一前一后盡可能多地兩兩匹配,用一個棧來模擬括號串的匹配即可。

還剩下的 \(0,1\) 還是盡量配對,用另一種往返票解決,有多出來的 \(0\)\(1\) 再使用單程票。

時間復雜度為 \(O((d+m)\log(d+m))\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(298\)\(\text{The Great Wall}\)\(\text{2020.10.19}\),自己做出)

題目大意:

\(n\) 段牆,每段牆有三種代價 \(a_i<b_i<c_i\),選擇兩個不同的長度為 \(r\) 的區間,不屬於任何一個區間的牆代價為 \(a_i\),屬於恰好一個區間的牆代價為 \(b_i\),屬於兩個區間交的牆代價為 \(c_i\),求代價和第 \(k\) 小的方案的代價。

\(n\leq 3\times 10^4\)


題解:

二分答案 \(M\),判斷是否有至少 \(k\) 個代價不超過 \(M\) 的方案。

我們首先可以將所有 \(a_i\) 提前算進答案,然后令新的 \(b_i\) 減去 \(a_i\),新的 \(c_i\) 減去 \(a_i+b_i\),接下來枚舉靠左區間的左端點,考慮靠右區間:

  1. 兩區間相交,那么代價為兩區間並的 \(b_i\) 和加上交的 \(c_i\) 和,可以寫成只與 \(x-1,y-1,x+r-1,y+r-1\) 四個位置的前綴和有關的一次式,我們已經知道 \(x,r\),用主席樹維護 \(y\) 處對應的值即可快速查詢 \(y\) 的數量。

  2. 兩區間不相交,那么代價就是兩個區間的 \(b_i\) 之和,同樣用主席樹維護長度為 \(r\) 的區間 \(b_i\) 和即可。

時間復雜度為 \(O(n\log^2 n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(285\)\(\text{Integral Polygons}\)\(\text{2020.10.19}\),自己做出)

題目大意:

給定凸 \(n\) 邊形,頂點為整點,求出有多少條對角線兩端面積都為整數。

\(n\leq 2\times 10^5\)


題解:

由 Pick 定理可知,一個格點多邊形面積為整數當且僅當所有邊上的點數之和為偶數。

顯而易見地,兩點間線段上點數之和(端點只算一個)為偶數當且僅當它們兩維坐標分別同奇偶。

因此一條對角線 \((x,y)\ (x<y)\) 滿足要求,當且僅當 \(s_y+s_x+f(x,y)=0\),其中 \(s_x\) 是前 \(x\) 條邊上的點數之和,\(f(x,y)\)\(x,y\) 之間線段上點數,\(+\) 為二進制加法(異或)。

考慮到對於確定的 \(y\)\(f(x,y)\) 只和 \(x\) 兩維坐標的奇偶性有關(\(4\) 種情況),\(s_x\) 只有 \(0,1\) 兩種需要的取值,所以只要用 \(8\) 個變量記錄每一種 \(x\) 的數量即可。

注意輸入的多邊形面積必須是偶數,否則直接輸出 \(0\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(235\)\(\text{Single Cut of Failure}\)\(\text{2020.10.19}\),自己做出)

題目大意:

有一個 \(w\times h\) 矩形框,其中有 \(n\) 條線段,每條線段連接框上兩點,求至少需要連多少條新線段,使得每條舊線段與至少一條新線段相交,保證舊線段端點兩兩不同且不在四個角上。

\(n\leq 10^6\)


題解:

顯然答案不超過 \(2\),因為只要連兩條對角線即可,所以只要判斷答案是不是為 \(1\)

我們將舊線段所有端點逆時針離散化,將編號為 \(i\)\(i+1\) 的兩點中間的一段框上區域稱為第 \(i\) 段,我們枚舉新線段的一端,那么對於每一條舊線段,對新線段另一端的限制就是一個區間,我們只需要將所有區間求交,看看是不是非空即可。

區間求交就是求左端點最大值和右端點最小值,用 set 來維護,同時在移動新線段的起始端時,如果跨過了某條舊線段的端點,那么那條舊線段所代表的區間會取反,一條舊線段最多取反兩次(只有兩個端點)。

注意由於是環上區間,第二次覆蓋到環開頭位置時需要將下標整體增加 \(n\)

時間復雜度為 \(O(n\log n)\),據說有線性做法。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(181\)\(\text{Graph}\)\(\text{2020.10.20}\),看了題解)

題目大意:

給定 \(n\) 個點 \(m\) 條邊的有向圖,添加至多 \(k\) 條邊使得字典序最小的拓撲排序字典序最大。

\(n,m,k\leq 10^5\)


題解:

模擬求解最小字典序拓撲序的過程,但我們增加一個輔助隊列 \(q2\),用來存想要放到之后加入拓撲序的編號較小的結點(以使得字典序變大),原隊列成稱為 \(q1\)

如果 \(q1\) 中取出最小值后仍有其他元素,並且 \(k\) 條邊還沒有用完,那么我們可以暫時將它存到 \(q2\) 中(因為可以先放 \(q1\) 中靠后的點,再通過加邊的限制使得編號小的點排在后面)。

如果 \(q1\) 中已沒有點,那么我們就只能從 \(q2\) 中取出最大點,將它放入當且拓撲序的末尾了,在構造加邊方案時,從之前拓撲序的最后一個點像這個點加一條邊即可保證求出來的一定是加邊情況下新圖字典序最小的拓撲序。

時間復雜度為 \(O(n\log n)\)\(n,m,k\) 同階)。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(183\)\(\text{Hack Protection}\)\(\text{2020.10.20}\),自己做出)

題目大意:

給定長度為 \(n\) 的序列 \(a_{1\ldots n}\),求出有多少個區間的 xor 和等於 and 和。

\(n\leq 10^5,\ \ a_i\leq 2^{31}-1\)


題解:

\(s_i\) 表示前綴異或和。

對於每一位,某個區間的 xor 和等於 and 和當且僅當它全是 \(1\) 且長為奇數,或不全是 \(1\)\(1\) 有偶數個。

首先考慮不全是 \(1\) 的情況,此時一段區間 \([l,r]\) 中每一位的 \(1\) 都有偶數個,顯然等價於 \(s_{l-1}=s_r\),要統計這樣的 \(l\) 的個數,只要一個主席樹就可以完成。

如果存在某些位全為 \(1\),那么我們設 \(las_i\) 表示當前狀態下前一個第 \(i\) 位為 \(0\) 的數下標是多少,那么我們可以枚舉有多少位是全為 \(1\) 的,可以通過 \(las_i\) 排序后的結果知道哪些位上全為 \(1\),並得到這些位全為 \(1\),其他位不全為 \(1\) 的區間范圍,這些位滿足 \(s_{l-1}\ne s_r\),其他位滿足 \(s_{l-1}=s_r\),因此我們將每一位相等或不等關系壓成一個二進制數,同樣在主席樹上查詢。

時間復雜度為 \(O(n\log^2 n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(291\)\(\text{Binary Code}\)\(\text{2020.10.20}\),自己做出)

題目大意:

給定 \(n\) 個長度和不超過 \(5\times 10^5\)\(01\) 串,每個串中最多有一個 \(?\),求一種將每個 \(?\) 換為 \(0\)\(1\) 的方案使得這些串兩兩不為前綴關系,或報告無解。

\(n\leq 5\times 10^5\)


題解:

首先將每個串中的 \(?\) 理解成 \(0\)\(1\) 分別都插到一棵字典樹上,我們將此時字典樹上插入過的一個字符串記為二元組 \((a,b)\)\(a\) 表示原來是第幾個串,\(b\) 表示其中 \(?\) 填的是 \(0\) 還是 \(1\)

從每一個 \((a,b)\) 對應的點往根結點走,如果路過另一個點 \((c,d)\),就說明當 \(a\)\(?\)\(b\)\(c\)\(?\)\(d\) 不能並存(否則就是前綴關系了),這顯然是 2-SAT 問題,跑個 Tarjan 就做完了。

稍微分析一下會發現,字符串不重復的情況下邊數不會超過 \(O(n^{\frac{4}{3}})\),猜測也有可能可以證到 \(O(n)\)

但是字符串可能會重復,這時候我們加一個特判,如果同樣的字符串出現了三次,那么必有至少兩次是一樣的,直接輸出無解。

時間復雜度為 \(O(n+e)\)\(e\) 為 2-SAT 建出的邊數。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(103\)\(\text{Boys and Girls}\)\(\text{2020.10.21}\),自己做出)

題目大意:

求長為 \(n\) 的由男生和女生組成的環,使得兩邊至少有一個男生的人數為 \(x\),兩邊至少有一個女生的人數為 \(y\),或報告無解。

\(n,x,y\leq 10^5\)


題解:

這題在 CF 上還 WA 着,OJ 上數據比較弱,等真正過了再寫。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(239\)\(\text{Triangles}\)\(\text{2020.10.21}\),自己做出)

題目大意:

給定一個 \(r\)\(c\) 列點陣(圖形見題面),有一些邊存在,數三角形個數。

\(r\leq 3000,\ \ c\leq 6000\)


題解:

先數正着放的三角形數量,反着放的同理。

顯然圖中所有三角形都是等邊三角形,我們枚舉水平的那條邊,判定兩側在它們那一行是否通過橫向邊聯通,以及向上延申是否可以相交,可以得到一個復雜度三方的做法。

我們只需要用數據結構優化這一過程,考慮每一行時,對於每個點 \(i\),求出它往左最多可以延申(向正左和左上都能擴展才算)的位置 \(l_i\) 和往右最多可以延申(向正右和右上都能擴展才算)的位置 \(r_i\),那么一對點 \((x,y)\) 滿足條件當且僅當 \(l_y\leq x< y\leq r_x\),這可以將 \(y\) 一維“離線”,從左往右掃 \(x\),用樹狀數組來維護當且所有滿足 \(l_y\leq x\)\(y\),對 \([x+1,r_x]\) 區間求和來實現。

時間復雜度為 \(O(rc\log c)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(281\)\(\text{Balanced Diet}\)\(\text{2020.10.21}\),自己做出)

題目大意:

\(m\) 種糖,每種糖有一個權值 \(a_i\),對於一個吃了 \(n\) 顆糖的方案,稱其是合法的當且僅當對於每一種糖 \(i\),設吃了 \(s_i\) 顆,滿足 \(\dfrac{na_i}{\sum a_i}-1<s_i<\dfrac{na_i}{\sum a_i}+1\)

給定一個長度為 \(k\) 的吃糖序列,保證每個前綴均合法,求最多還能吃多少顆糖,使得仍然保持每個前綴均合法,或報告可以無限吃下去。

\(m,k,\sum a_i\leq 10^5\)


題解:

貪心,設 \(t_i\) 表示當前情況下滿足 \(\dfrac{na_i}{\sum a_i}-1<s_i\) 的最大的 \(n\),每次選擇 \(t_i\) 最小的位置,吃一顆對應的糖,直到 \(t_i\) 比當前總糖數還少,用優先隊列來實現。

證明一下,其實這種決策的不劣性是顯然的(即使去吃別的糖,也必須在 \(t_i\) 顆內再吃一次這種糖),所以只要證明可行性,事實上這種方案一定是可行的,因為我們有 \(\sum\limits_{i=1}^m \dfrac{a_i}{\sum a_i}=1\),所以一定存在一種糖使得 \(s_i\leq \dfrac{na_i}{\sum a_i}\),那么吃一種這顆糖是不會超過最大限制的,因為此時 \(s_i+1\leq \dfrac{na_i}{\sum a_i}+1<\dfrac{(n+1)a_i}{\sum a_i}+1\)

最后要判定是否可以無限吃下去,在數據范圍中已經明示,不難猜想當吃到 \(\sum a_i\) 顆糖時即可無限吃下去,可以感性理解為吃了這么多糖以后每種糖的 \(s_i\)\(n\) 的關系被卡死,一定和初始狀態是一樣的。

時間復雜度為 \(O((\sum a_i)\log m+k)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(227\)\(\text{Branch Assignment}\)\(\text{2020.10.22}\),自己做出)

題目大意:

給定 \(n\) 個點 \(m\) 條邊的有向帶權圖,定義 \(i,j\) 兩個點聯絡代價為從 \(i\) 途徑 \(b+1\) 走到 \(j\) 的最短路長,將 \(1,\ldots,b\) 號點分成 \(s\) 個集合,使得同一個集合內兩兩聯絡代價和之和最小。

\(n\leq 5000,\ \ m\leq 5\times 10^4\)


題解:

\(i\)\(n\) 的最短路為 \(b_i\)\(n\)\(i\) 的最短路為 \(c_i\),令 \(a_i=b_i+c_i\),對於分出的大小為 \(k\) 的集合,可知其中每個點 \(i\) 對聯絡代價和的貢獻都是 \((k-1)(b_i+c_i)=(k-1)a_i\)

我們將所有點按照 \(a_i\) 從小到大排序,通過一番胡亂推導或感性理解會發現:最優方案中每個集合一定都是一個區間,且靠后的區間長度更短。

簡單說明一下,后者比較顯然,如果后面的集合更大,那么只要把一部分分給較小的靠前的集合,答案會變小;而前者是后者的推論,如果有個集合不是區間,那么將不連通的部分與另一個有相鄰元素的集合的相鄰部分交換一下,會更優。

這樣以后可以 DP,直接 DP 不優化的是 \(O(n^3)\),聽說可以四邊形不等式,不過這里我采用了 wqs 二分,然后基本就是個裸題,不多贅述。

時間復雜度為 \(O(n^2\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(135\)\(\text{Chain & Co.}\)\(\text{2020.10.22}\),自己做出)

題目大意:

給定三維立體中 \(n\) 個相同尺寸的正方形框,兩兩邊線無交點,求能否分成兩個子集 \(A,B\),使得對於任意 \(x\in A,y\in B\)\(x,y\) 不能分離(即不能把 \(y\) 脫離 \(x\) 獨立拉出來)。

多組數據。

\(\sum n\leq 10^6\)


題解:

將正方形框分成三類:分別是平行於 \(xy,yz,zx\) 平面的。

顯然對於同一類正方形框,由於邊界不相交,所以要么是異面,要么是在同一平面上但相離,那么它們不能分屬 \(A,B\) 兩個集合,只能屬於同一個集合。

所以只要枚舉一下,將三類點分成兩個集合,剩下的就是要判定三類點中每兩類點是不是兩兩不能分離的(隨便從兩類點中各選出一個都不能分離)。

如果固定了另一個框的方向,那么對於一個確定的框來說,滿足另一個框與它不能分離的那個框的某個特征點(如左下角點)的軌跡是一個可以求出的長方體,我們枚舉一類點,將所有這樣的長方體取交,再判定另一類點是否都在這個交集中即可。

時間復雜度為 \(O(\sum n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(241\)\(\text{Lonely Mountain}\)\(\text{2020.10.22}\),自己做出)

題目大意:

給定三維多面體在 \(xz,yz\) 兩面上的投影(分別是包含 \(n_x,n_y\) 個端點的折線段),保證兩方向輪廓線都是向上寬度遞減的底部 \(z\) 坐標為 \(0\) 的連通區域,求多面體最小體積,或報告無解。

\(n_x,n_y\leq 10^5\)


題解:

如果兩維投影最大高度相等,那么有解,否則無解。

首先考慮兩維寬度都隨高度線性遞減的情況,即兩維投影都是梯形(或退化成三角形),此時設六面體下底面為 \(a\times b\),上底面為 \(c\times d\),通過積分或者割補可以知道體積為 \(\dfrac{(a-c)(b-d)}{3}+\dfrac{ad+bc}{2}\)

如果兩維投影是更復雜的折線,我們只需沿着所有拐點的 \(z\) 坐標將折線下方的區域切分成若干個梯形或三角形的並,對於每一段梯形和三角形做一次上面的事情即可(注意上面的面積結論當這個梯形的雙底被分割成好幾段不連續區間的時候也是成立的,所以有多峰的情況並不影響答案)。

在同一段內,寬度隨高度遞減,其遞減速率可以通過一條從下到上的掃描線算出,掃描時記錄當前與掃描線相交的所有折線段的斜率總和,那么這個斜率總和就是寬度隨高度遞減的速率。

時間復雜度為 \(O((n_x+n_y)\log(n_x+n_y))\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(253\)\(\text{Fragmentation}\)\(\text{2020.10.23}\),自己做出)

題目大意:

給定序列 \(a_{1\ldots n}\),求一種分段方法,使得在不改變同一段內數的順序的情況下可以將序列排序。

\(n\leq 10^5\)


題解:

一段連續的相同的數顯然可以縮起來,縮完之后離散化一下,設得到的新序列為 \(b_{1\ldots m}\)

可以發現 \(i\)\(i+1\) 兩個數處於同一段中的情況最多只會出現一次(否則兩個包含 \(i\ \ i+1\) 的段無法排序),所以答案其實取決於存在 \(i,i+1\) 處於同一段的 \(i\) 的數量。

於是我們令 \(dp(j)\) 表示當 \(b_j,b_{j-1}\) 這兩個數處於同一段(前提是 \(b_j=b_{j-1}+1\))時,序列里不超過 \(b_{j-1}\) 的數中最多有多少對 \((k,k+1)\) 處於同一段,我們按照 \(b_j\) 從小到大更新,為了方便轉移,我們對狀態稍作修改,\(dp(j)\) 可以是 \(b_j,b_{j-1}\) 處於一段,也可以是不處於一段(要看哪個答案更小),這時 \(j\) 的取值就不需要滿足 \(b_j=b_{j-1}+1\) 了。

第一種轉移是 \(b_j,b_{j-1}\) 不在同一段,\(dp(y)\to dp(j)\),這里 \(y\) 就是任意的,只要 \(b_y<b_j\) 即可。

第二種轉移是把 \(b_j,b_{j-1}\) 放在一段里,\(dp(y)+1\to dp(j)\),這里 \(y\) 也沒有什么限制,但是有一條規則:如果 \(y=j-1\),並且 \(b_y,b_{y-1}\) 也在同一段中,那么就意味着 \(b_{j-2},b_{j-1},b_j\) 都在同一段中,當且僅當 \(b_{j-1}\) 在整個序列中只出現過這一次時才能這么轉移(否則會漏掉別的地方的 \(b_{j-1}\))。

具體實現時為了輸出方案,還要對每個狀態記錄前驅狀態,再額外記錄一個 \(dn(j)\) 表示 \(dp(j)\) 這個狀態中是否把 \(b_j,b_{j-1}\) 放在了一段。

時間復雜度為 \(O(n\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(246\)\(\text{Digital Addition}\)\(\text{2020.10.23}\),自己做出)

題目大意:

給定一個電子鍾字體書寫的兩數加法豎式(兩個加數以及和分別寫在三行),三個數位數都為 \(w\)(可能有前導零),但是由於顯示出了問題,下一行的數的最上方一條線會重疊顯示在上一行的數的中間那條線上,右邊一列的數的最左邊一條線會重疊顯示在左邊一列的數的最右邊那條線上,求一種可能的豎式或報告無解。

\(w\leq 100\)


題解:

由於 \(w\) 非常小,隨便做做就可以。

\(dp(i,j,k,l)\) 表示最后 \(i\) 位,第 \(i\) 位上三個數分別是 \(j,k,l\) 時是否可行,如果可行還需要記錄前驅狀態。

轉移時只需要暴力枚舉(總共的 \((j,k,l)\) 也不超過 \(200\) 組),可以根據每一列的橫向線來除掉一些無用狀態,此后就是模擬相鄰兩列六個數的狀態,是否和給定的示數相等即可。

實現方法就不具體寫了。

時間復雜度為 \(O(D^4\times w)\),其中進制數 \(D=10\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(262\)\(\text{Laminar Family}\)\(\text{2020.10.23}\),自己做出)

題目大意:

給定一棵 \(n\) 個點的無根樹和樹上的 \(m\) 條路徑,求是否存在兩條路徑相交而不為包含關系。

\(n,m\leq 10^5\)


題解:

兩條路徑相交,那么它們的最淺點(稱為路徑的 LCA)顯然必須是祖先-后代關系。

將路徑的相交分成兩種,一種是 LCA 相同,另一種是 LCA 不同,只需分別判定這兩類的所有相交是否都是包含關系即可。

第一類:LCA 相同:

我們只需要枚舉 \(x\),對以 \(x\) 為 LCA 的路徑按照長度從小到大排序,判定是否相鄰兩條路徑都是包含關系,如果是那么就說明它們兩兩都是包含關系。

第二類:LCA 不同:

我們考慮對於每條路徑(設其 LCA 為 \(u\)),求出 LCA 是 \(u\) 后代的路徑中有多少條與它相交,又有多少條是它的子路徑,然后看看是不是都相等就可以了。

  1. 相交:對於每條路徑,給其 LCA 的權值加上 \(1\),那么求出與一條路徑相交的 LCA 為后代的路徑有多少條與它相交,就是一個鏈上求和,預處理一下到根的前綴和即可。

  2. 包含:對於路徑 \((u,v)\),如果 \(u,v\) 不是祖先-后代關系,那么這條路徑不可能是一條 LCA 深度更小路徑的子路徑(因為在其 LCA 處分成兩支),否則,設 \(u\)\(v\) 的祖先,那么它是所有滿足 LCA 為 \(u\) 祖先,一支在 \(v\) 子樹內的路徑的子路徑,對此我們將每條路徑記錄在其 LCA 上,然后進行一次線段樹合並,遇到上述路徑 \((u,v)\) 時在 \(u\) 的樹上給 \(v\) 的所有后代做一個區間加,查詢時只要查一條路徑兩端點處在 LCA 所對應線段樹上的值即可,注意用標記永久化減小空間。

時間復雜度為 \(O((n+m)\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(178\)\(\text{ASCII Puzzle}\)\(\text{2020.10.23}\),自己做出)

題目大意:

完成一個 \(n^2\) 塊拼圖的 \(nh\times nw\) 拼圖謎題(給定拼圖碎片的規則見題面)。

\(n\leq 4,\ \ 3\leq w,h\leq 5\)


題解:

首先特判 \(n=1\) 的情況,剩余的情況都會有四個角落。

首先找到拼圖所在“平凡塊”的四角,然后可以求出對應的四條邊是否是光滑的。

如果有兩條邊都是光滑的,那么一定放在對應的角落上,如果有一條邊是光滑的那么一定放在對應的邊上,剩下的就放中間。

同一條邊上的拼圖順序和內部拼圖順序暴搜即可。

時間復雜度為 \(O(n^2wh\times T)\)\(T\) 是最大的情況數,在 \(n=4\)\(T=2^4\times 4!=384\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(141\)\(\text{Tarot Sham Boast}\)\(\text{2020.10.24}\),自己做出)

題目大意:

隨機一個字符集為 \(\{R,S,P\}\) 的長為 \(n\) 的字符串 \(T\),給定 \(s\) 個模式串 \(S_{1\ldots s}\),按照它們在 \(T\) 中作為子串出現的概率排序(如果概率相同按照輸入順序排序)。

\(n\leq 10^6,\ \ s\leq 10,\ \ |S_i|\leq 10^5\)


題解:

根據歌唱王國的結論,模式串 \(S\) 在隨機文本串中第一次出現的位置期望為 \(\sum\limits_{b\in B} |\Sigma|^b\),其中 \(B\)\(S\)\(Border\) 長度集合。

據此不難猜想:本題中按每個長度是不是模式串的 Border 得到每個串對應的一個新的 \(01\) 串,這些 \(01\) 串的字典序排序結果就是答案(也就是兩個模式串最長的不同長度的 Border,如果其中一個更長,那么對應模式串出現的概率就更低)。

但是我們要注意有些 Border 是沒有用的,用一個簡單的容斥來理解,我們統計一個串出現的概率時用它在每個位置出現的概率減去多個位置同時出現的概率,而 \(S_i\) 的一個 Border 長度 \(x\) 如果滿足 \(2|S_i|-x>n\),那么以 \(x\) 為公共前后綴時兩個 \(S_i\) 放不進長度為 \(n\)\(T\) 中,所以這個 Border 是無用的,要去掉。

根據上述感性理解,用 KMP 求一下 Border 就做完了。

過題之后找了下題解,具體證明我看不懂:http://www.csc.kth.se/~austrin/icpc/tarotshamproof.pdf

時間復雜度為 \(O(s\sum |S_i|)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(286\)\(\text{Kitchen Knobs}\)\(\text{2020.10.24}\),自己做出)

題目大意:

順序給定 \(n\) 個包含 \(7\) 個一位數的輪盤,每個輪盤有一個初始指針,定義其示數為從初始指針開始順時針讀取一周得到的七位數,每一次操作可以將一個區間中所有輪盤的初始指針朝同一方向轉動一個固定的角度,求至少多少次操作可以使所有輪盤都顯示其可能的最大示數。

\(n\leq 500\)


題解:

如果一個輪盤上所有數都一樣,那么直接刪除它,這對答案沒有任何影響。

否則,一個輪盤的最大示數對應的指針位置是唯一的(否則可以證明 \(1,\ldots,7\) 都是它的 Border 長度,從而每一位相等),我們求出這個指針位置和初始位置的差值,即為需要轉動的格數。

於是問題轉化成了:將一個初始全 \(0\) 的序列最少做幾次區間加法,可以得到給定序列?

對給定序列差分,可以進一步轉化成:將一個初始全 \(0\) 的序列每次選擇兩個數一加一減一個相同的值(或只修改一個數),最少幾次可以得到給定序列?

注意,上述操作都是在 \(\bmod 7\) 意義下的,值域也都是 \([0,6]\)

如果一次操作中改變了 \(a,b\) 兩位置上的數(\(a<b\)),另一次操作改變了 \(b,c\) 兩位置上的數(\(b<c\)),那么我們可以將它用一次對 \(a,c\) 的操作和一次對 \(b,c\) 的操作來等效,所以存在一個最優方案,使得不存在一個 \(b\) 既和前面的數同時操作過,又和后面的數同時操作過。

如果一個 \(b\) 只和前面的某些數(記為 \(S\))同時操作過,那么 \(b\) 當然就等於 \(S\) 中所有元素的和的相反數,也就是 \(\{b\}\cup S\) 的元素和為 \(0\),一個子集和為 \(0\) 對應着一個 \(b\) 可以通過之前的操作變為給定的數。

所以問題進一步轉化為:最多可以從給定序列中分出多少和為 \(0\) 的子集?

我們首先證明,假設 \(a+b=0\),那么一定存在一個最優方案,使得每個 \(a\) 都與 \(b\) 組成一個子集,或每個 \(b\) 都與 \(a\) 組成一個子集。這是因為假設結論不成立,那么有一個 \(a\) 與另一些數 \(S_1\) 組合,有一個 \(b\) 與另一些數 \(S_2\) 組合,可以換成 \(a,b\) 組合,\(S_1,S_2\) 組合。

於是本來有 \(6\) 種數(\(1,2,3,4,5,6\)),通過這樣的兩兩匹配只會剩下三種(\(1,6\) 中較多的那種,\(2,5\) 中較多的那種,\(3,4\) 中較多的那種)。

然后就可以 DP 了,設 \(dp(i,j,k)\) 表示當三種數分別有 \(i,j,k\) 個時最少操作數,那么 \(dp(i-a,j-b,k-c)+a+b+c-1\to dp(i,j,k)\),其中 \(a\) 個第一種數,\(b\) 個第二種數,以及 \(c\) 個第三種數的和為 \(0\)

由於 \(7x\equiv 0\),所以 \(a,b,c\leq 6\)(除了 \(a=7,b=c=0\) 及兩種對稱情況外),由於 \(7\) 是素數,所以與小於它的所有數互素,一旦確定 \(a,b\) 也就確定了 \(c\),所以這樣的 \((a,b)\)\(49\) 對,復雜度可以接受。

時間復雜度為 \(O(n^3P^2)\)\(P=7\) 為模數。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(154\)\(\text{Evolution in Parallel}\)\(\text{2020.10.25}\),自己做出)

題目大意:

給定字符串 \(S\)\(n\) 個字符串 \(T_1,\ldots,T_n\),求所有 \(T_i\) 是否都是 \(S\) 的子序列,並且將 \(T_i\) 划分為 \(2\) 個集合,使得同一個集合內的字符串兩兩是子序列關系。

\(n\leq 4000,\ \ |S|,|T_i|\leq 4000\)


題解:

先把存在 \(T_i\) 不是 \(S\) 子序列的情況判掉。

然后 DP,將 \(T_i\) 按長度從小到大排序,設 \(dp(i,j)\) 表示將 \(T_1,\ldots,T_i\) 分成兩列,最后一個串分別是 \(T_i\)\(T_j\) 時是否可行,如果可行那么還要記錄前驅。

暴力轉移,如果 \(dp(i,j)\) 可行且 \(T_j\)\(T_{i+1}\) 的子序列,那么 \(dp(i+1,i)\) 也可行;如果 \(T_i\)\(T_{i+1}\) 的子序列,那么 \(dp(i,j)\) 可以轉移到 \(dp(i+1,j)\)

這里我也沒想到怎么優化,隨便優化一下常數就過了。

時間復雜度為 \(O(n^3)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(190\)\(\text{Landscape Improved}\)\(\text{2020.10.25}\),自己做出)

題目大意:

\(w\) 堆石塊從左到右排列,第 \(i\) 堆包含 \(h_i\) 個石塊,你需要添加不超過 \(n\) 個石塊,滿足每個新加的石塊的左下和右下都需要有一個石塊,使得最高的石堆高度最大。

\(w\leq 10^5,\ \ n\leq 10^{18}\)


題解:

二分答案 \(m\),枚舉添加后高度為 \(m\) 的石堆 \(i\),從 \(i\) 向兩邊搜至少要將石塊添加到哪里才能使得每個新加的石塊的左下和右下都有一個石塊,這個可以用 ST 表維護 \(h_i+i\)\(h_i-i\) 的最小值來求出。

時間復雜度為 \(O(w\log w\log \sqrt n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(270\)\(\text{Pork barrel}\)\(\text{2020.10.25}\),自己做出)

題目大意:

給定 \(n\) 個點 \(m\) 條邊的無向帶權圖,\(q\) 次詢問僅保留權值在一個區間中的邊時,連通塊數最少的最小生成森林的邊權和。

多組數據。

\(\sum n\leq 10^5,\ \ \sum m\leq 5\times 10^5,\ \ \sum q\leq 10^6\)


題解:

類似須臾幻境,不過我們會發現選取的邊是邊權盡量偏小的邊,所以我們需要按照邊權從大到小倒着做。

用個 LCT 維護當且的 MST,由於詢問的權值和權值區間是同一個權值,所以直接求權值 MST。

最后用主席樹維護每個時刻的答案。

時間復雜度為 \(O((m+q)\log n+n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(277\)\(\text{Tours}\)\(\text{2020.10.25}\),自己做出)

題目大意:

給定 \(n\) 個點 \(m\) 條邊的無向圖,求出所有可能的 \(k\),使得給每條邊一個 \([1,k]\) 的整數權值,能夠使得每個長度不小於 \(3\) 的簡單環上每種權值出現次數相等。

\(n,m\leq 2000\)


題解:

相交的不同的環可以異或出新的區間,我們發現任意多個環相加減(相異或)得到的必須仍然是每個權值出現次數一致的邊集,也容易證明只要 \(k\) 是所有這樣邊集的公因數就滿足條件。

而兩條邊永遠同時出現或不出現在這樣的邊集,當且僅當覆蓋它們的環的集合完全一致。

所以我們求出一個 DFS 樹,每條非樹邊隨機賦一個權值,然后一條樹邊的權值等於跨過它的所有非樹邊的權值異或,最后數除了 \(0\) 之外所有權值等價類大小的 \(\gcd\),它的所有因數就是答案。

時間復雜度為 \(O(m\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(247\)\(\text{The Imp}\)\(\text{2020.10.26}\),自己做出)

題目大意:

\(n\) 個物品,第 \(i\) 個物品價值為 \(v_i\),價格為 \(c_i\),但是你每買下一個物品,小鬼都有可能把它變成價值為 \(0\) 的灰塵,不過最多 \(k\) 個商品會被變成灰塵,如果你買到一個物品且沒有變成灰塵,那么你必須帶着它離開。

求出你和小鬼都最優決策的情況下,你能賺到多少錢(賺到的錢數即得到的物品的價值減去買過的所有物品的價格之和)。

\(n\leq 1.5\times 10^5,\ \ k\leq 9\)


題解:

貪心,可以證明存在一種最優決策,買的順序是按價值從小到大的,這是因為如果前后兩個買的物品前一個價值更大,那么交換一下不會更劣。

接下來直接做不好設計狀態,所以考慮二分答案 \(m\),這樣限制就變成了:任意前 \(i\) 個買的物品價格和加上 \(m\) 不能大於第 \(i\) 個物品的價值。

於是和狀態有關的變量就只有:考慮前多少個物品,選了多少個物品,滿足條件下的總價格和,於是令 \(dp(i,j)\) 表示從前 \(i\) 個物品中選 \(j\) 個,滿足二分條件的情況下價格和最小是多少。

那么 \(dp(i,j)\to dp(i+1,j)\),並且在滿足 \(dp(i,j)+c_{i+1}+m\leq v_{i+1}\) 時有 \(dp(i,j)+c_{i+1}\to dp(i+1,j+1)\),最后檢驗是否 \(dp(n,k)\) 不是初始的無窮大即可。

時間復雜度為 \(O(nk\log (\sum v_i))\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(233\)\(\text{Rubik's Rectangle}\)\(\text{2020.10.26}\),自己做出)

題目大意:

一個 \(n\times m\) 的矩陣,其中 \(1\)\(n\times m\) 中所有數都恰好出現一次,每次操作可以翻轉一行或一列的數的順序,需要把最終矩陣通過不超過 \(10nm\) 操作變成按照先行后列排好序的狀態,或報告無解。

\(n,m\leq 100\)


題解:

這題似乎對玩過魔方的人比較友好。

一個顯然的觀察是:一個數字只能出現在最多四個位置上(因為行列只有最多兩種情況),所以我們看一下所有這樣四個位置上的數和最后四個數一不一樣,如果有不一樣那么直接無解。

接下來考慮一種情形:第一行和最后一行,第一列和最后一列都已經拼好,現在要拼中間區域,對於中間區域中某四個中心對稱的格子來說,在復原它們的相對位置時就不能改變任何其他行列的狀態(可以進行兩行和兩列的操作,並且每行每列都要操作偶數次)。

畫幾張圖理解一下,發現我們能做的基本操作類型是 \(ABAB\),其中 \(A,B\) 分別是一行和一列,這個操作的效果其實是對四塊中的三塊做了一個三輪換。

(如果對魔方比較熟悉就會很快發現這個結論,因為這個結構其實就是調頂棱位置時候的操作)

但是這里沒有很嚴格的什么次數限制,所以我們先把左上角那個數通過若干次操作歸位,再看看剩下三個數能不能轉一次歸位。

而對於第一行和最后一行,第一列和最后一列的數,我們還可以加上對一列或一行的操作,此時一定可以歸位。

時間復雜度為 \(O(nm)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(287\)\(\text{Subway}\)\(\text{2020.10.26}\),自己做出)

題目大意:

\(n\) 個站點和連接它們的 \(m\) 條線路(若干條邊組成的鏈),線路總長為 \(L\),問從一個站 \(A\) 到另一個站 \(B\) 至少需要坐上幾條不同的線,以及在此情況下最多可以坐幾站路(一條線不能正反都坐)。

\(n\leq 3\times 10^5,\ \ m\leq 10^5,\ \ L\leq 10^6\)


題解:

對於每個站點建一個頂點,再對於每條線路拆成正反兩條,分別對於線路上每一個站點新建一個頂點,並且按照線路順序連接(邊權為 \(0\)),線路上每個頂點再和對應站點一開始建的那個點互相連邊,令走過去的權值為 \(0\),走回來的權值為 \(1\)

那么第一問的答案就是兩個點之間的最短路。

第二問是最長路,不能直接做,不過我們只要提取第一問源點出發的最短路 DAG,在這個 DAG 上拓撲排序求最長路即可。

時間復雜度為 \(O(L\log L)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(138\)\(\text{Distribution in Metagonia}\)\(\text{2020.10.26}\),自己做出)

題目大意:

給定 \(n\),拆成若干個互不為倍數關系的 \(2^i3^j\) 之和。

一個測試點有 \(T\) 組數據。

\(n\leq 10^18,\ \ T\leq 1000\)


題解:

設求解過程為 \(Solve(n)\)

首先,如果 \(2\mid n\)\(3\mid n\),直接把這個 \(2\)\(3\) 提出,接着 \(Solve(n/2)\)\(Solve(n/3)\)

如果 \(2,3\) 都不是 \(n\) 的因數,那么顯然 \(n\) 的分拆中一定又會有 \(2^p\),又會有 \(3^q\),根據直覺和題面沒有寫無解判定的情況來看,應該是不可能無解的,所以我們只要找到一個 \(2^p\),使得 \(3\mid (n-2^p)\),這樣剩余的數里都會有 \(3\),即 \(2^p\) 不是它們的倍數,在此基礎上我們令 \(p\) 最大,也能滿足 \(2^p\) 不是其他 \(2^i3^j\) 的倍數。

因為 \(3\) 不是 \(n\) 的因數,所以 \(n\equiv 1\bmod 3\)\(n\equiv 2\bmod 3\),設 \(p_0=\lfloor\log n\rfloor\),那么 \(2^{p_0}\equiv n\)\(2^{p_0-1}\equiv n\) 必有一個成立。

時間復雜度為 \(O(T\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(194\)\(\text{Export Estimate}\)\(\text{2020.10.27}\),自己做出)

題目大意:

給定 \(n\) 個點 \(m\) 條邊的帶權無向圖,\(q\) 次詢問,每次給定 \(k\),詢問只保留邊權不小於 \(k\) 的邊時按照下列原則縮點后剩余圖的點數和邊數:

  • \(1\)\(n\) 枚舉 \(i\)

  • 如果 \(i\) 當前的度數恰好為 \(2\) 並且不存在到自己的自環,那么刪除它和這兩條邊,並在這兩條邊的另外兩個端點之間連邊。

\(n,m,q\leq 3\times 10^5\)


題解:

從大到小加邊,就變成了動態維護當前圖縮點后的點數和邊數。

只看二度點,那么二度點構成的連通塊只有鏈或者環,如果是鏈的話那么最后會全縮掉,如果是環的話最后會剩一個點。

用並查集維護連通性,對於每個連通塊維護其中是否存在度數超過 \(2\) 的點,如果不存在則再維護一下這個連通塊是不是環。

如果連一條邊后變成了環,那么會少縮掉一個點兩條邊,如果連一條邊后本來是環變成了存在三度點,那么破環成鏈。

在這過程中順便維護點數和邊數的變化情況,具體細節由於我也忘了所以就不寫了。

時間復雜度為 \(O(n\log n)\),這里把 \(n,m,q\) 都當成一個量級了。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(230\)\(\text{Metal Processing Plant}\)\(\text{2020.10.27}\),自己做出)

題目大意:

\(n\) 個點,給出任意兩點之間距離(不一定滿足三角形不等式),將它們分成兩個點集 \(A,B\),使得兩者內部最遠點對距離之和最小。

\(n\leq 200\)


題解:

將所有距離從大到小排序為 \(d_1,\ldots,d_{\frac{n(n-1)}{2}}\),枚舉兩個最遠距離中較大的那個 \(d_i\)(不妨設為 \(A\) 中的最遠距離),那么 \(d_1,\ldots,d_{i-1}\) 這些邊的兩個端點必須分別在兩邊,在它們之間連邊,如果不是二分圖那么說明無解,否則每個二分圖連通塊的兩部必須分屬兩個集合。

接下來考慮另一個最遠距離(\(B\) 中的最遠距離)最小是多少,考慮二分答案 \(d_j\),那么 \(d_{i+1},\ldots,d_{j-1}\) 這些距離不能同時屬於 \(B\),這時不是二分圖關系,而是 2-SAT 判定,我們將前面說的那個二分圖的每個連通塊的兩部看出兩個點,根據二分答案得到的這些關系建出 2-SAT 圖判定是否有解,即可判定二分的答案是否可行。

由於只有二分圖某個連通塊的兩部變化時二分答案那一部分的情況才會變化,所以只有二分圖發生改變時才重新進行二分答案,而二分圖改變最多 \(n-1\) 次,所以第二個過程最多只會做 \(n\) 次。

時間復雜度為 \(O(n^3\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(191\)\(\text{Frightful Formula}\)\(\text{2020.10.28}\),自己做出)

題目大意:

有一個 \(n\times n\) 矩陣 \(F_{n\times n}\),給定第一行和第一列的數,其余某個位置 \((i,j)\) 上的數 \(F_{i,j}=aF_{i-1,j}+bF_{i,j-1}+c\),求 \(F_{n,n}\) 的值,對 \(10^6+3\) 取模。

\(n\leq 2\times 10^5\)


題解:

一開始遇到一個式子不太會算到 E 群問了一下,結果被講了一些聽不懂的東西,最后我這個做法似乎是一個不太本質的做法......

可以發現整個式子里面 \(c\) 的貢獻和另外兩個東西的貢獻可以拆開,另外兩個東西很好算,枚舉從第一行或第一列中哪個位置轉移,乘上一個類似 \(\binom {i+j}{i} a^ib^j\) 的式子就可以了。

\(c\) 是不太好算的,我是手算了一個 \(5\times 5\) 的表格,令 \(C_{i,j}\) 表示從 \((0,0)\) 走到 \((i,j)\) 時的 \(c\) 前的系數,轉移是 \(C_{i,j}=aC_{i-1,j}+bC_{i,j-1}+1\),然后發現似乎 \(C_{i,j}=C_{i-1,j}+C_{i,j-1}-C_{i-1,j-1}+\binom {i+j}{i} a^ib^j\),嘗試用組合意義來解釋,最后那個 \(\binom {i+j}{i} a^ib^j\) 就是從 \((0,0)\) 一直按照 \(a,b\) 的規則走到 \((i,j)\),然后再變成 \(c\) 的貢獻,而前面那個其實是一個前綴和的形式(這一段憑印象寫的,如果錯了請指出)。

所以 \(c\) 的系數就是 \(\sum\limits_{i=0}^{n-2}\sum\limits_{j=0}^{n-2} \binom {i+j}{i} a^ib^j\)

\(Sum_i=\sum\limits_{j=0}^{n-2} \binom {i+j}{j} b^j\),根據組合恆等式列出 \(Sum_i\)\(Sum_{i-1}\) 間的方程,可以解得:

\[Sum_i=\dfrac{\binom {i+n-2}{n-2} b^{n-1}-Sum_{i-1}}{b-1} \]

如果 \(a\ne 1\) 或者 \(b\ne 1\) 都可以按照這個遞推,如果 \(a=b=1\) 那么上面這個式子是經典恆等式,值為 \(\sum\limits_{i=1}^{n-1} \binom {n-1} i ^2\)

時間復雜度為 \(O(n\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(261\)\(\text{First of Her Name}\)\(\text{2020.10.28}\),自己做出)

題目大意:

給定 \(n\) 個點的字典樹,字符集為 \(\Sigma\),有 \(q\) 次詢問,每次詢問有幾個結點代表的串(從根結點走到這個點的串)以 \(T\) 為后綴(按照原題意是以 \(T\) 翻轉過來為后綴)。

\(n\leq 2\times 10^6,\ \ \sum |T|\leq 2\times 10^6,\ \ |\Sigma|=26\)


題解:

是個愛怎么做就怎么做的字符串題。

首先嘗試樹上 SA,將詢問串放在一起或者詢問時二分,然后被 cyj 大毒瘤卡常了。

然后嘗試廣義 SAM,順着 \(T\) 走到對應點數一下大小,就過了。

時間復雜度為 \(O(n+\sum |T|)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(110\)\(\text{Heavy Chain Clusterization}\)\(\text{2020.11.01}\),自己做出)

題目大意:

給定 \(n\) 個字符串 \(S_1,\ldots S_n\),將它們分成最少的組,使得同一個組內長度為 \(k\) 的前綴都相同或長度為 \(k\) 的后綴都相同。

\(n\leq 5000,\ \ k\leq |S_i|\leq 550\)


題解:

將每個串的長度為 \(k\) 的前后綴分別哈希,離散化后在前后綴之間連邊,答案就是最小點覆蓋,也就是最大匹配,跑一次 dinic 就求出來了。

時間復雜度為 \(O(\sum |S_i|+n\sqrt n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(243\)\(\text{Kingdom Trip}\)\(\text{2020.11.01}\),自己做出)

題目大意:

給定二維平面中 \(n\) 個點 \(p_1,\ldots,p_n\),選擇其中一個子序列,使得對於不屬於這個子序列的每個 \(p_i\),它到它在子序列中的前驅后繼連線段的距離不超過 \(d\),求子序列至少包含幾個點。

\(n\leq 2000\)


題解:

只要求出所有 \(trans(i,j)\) 表示是否 \(\forall k\in [i+1,j-1]\) 都到 \(p_ip_j\) 距離小於 \(d\),這個求完之后再 \(n^2\) DP 一下就行了。

枚舉 \(i\),從前到后掃描 \(k\),如果 \(|p_ip_k|\leq d\) 那么沒有限制,否則 \(k\) 就對 \(p_ip_j\) 的角度有一個區間范圍的限制,維護前面所有這些區間的交,看看 \(p_j\) 相對 \(p_i\) 是不是落在這個區間里,就完成了判定。

時間復雜度為 \(O(n^2)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(111\)\(\text{Hidden Supervisors}\)\(\text{2020.11.01}\),自己做出)

題目大意:

有一個 \(n\) 個點的以 \(1\) 為根的有根樹,某些點的父結點未定,確定這些點的父結點使得整個樹的最大匹配數最大。

\(n\leq 10^5\)


題解:

先求出每個連通塊的最大匹配(為了記錄每個點在不在最大匹配中,最好采用貪心法求最大匹配),再記錄一下這個連通塊的最大匹配是否一定包含根結點。

如果一個連通塊的最大匹配包含根結點,那么直接把這個根結點連到 \(1\) 的下面(因為接到其他點下面也不能匹配,沒有用),然后用一個隊列維護當前與 \(1\) 連通的點中沒有匹配的點的數量,再用一個優先隊列維護不與 \(1\) 連通的連通塊中未匹配點數最多的那個。

每次取出優先隊列中的隊首,將根結點掛在與 \(1\) 連通的一個沒有匹配的點下面(這樣形成了一組匹配),如果不存在這樣的點那么只好隨便找一個點連(比如直接當成 \(1\) 的兒子),因為我們是按照未匹配點數從大到小加的,所以盡量保證了當前能夠存在一個沒匹配的點,所以這個貪心是最優的。

時間復雜度為 \(O(n\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(125\)\(\text{Baggage}\)\(\text{2020.11.01}\),自己做出)

題目大意:

有一個長為 \(2\times n\) 的序列,形如 \(\text{BABA...BA}\),每次操作可以選擇連續兩個字符(不能選到空位),放到另一處連續的兩個空位中(第一個位置前面都是空位),然后這兩個字符原來的位置會變成空位。

你需要用最少的操作次數使得序列變成 \(\text{AA...AABB...BB}\),起始位置任意但必須連續。

\(n\leq 100\)


題解:

構造題,沒有什么技巧和算法可言。

首先有端猜測答案就是 \(n\)

題目里送了兩組樣例,一個是 \(5\),一個是 \(8\),以此為基礎推一下 \(n=9\)\(n=12\),那么模 \(4\)\(1\)\(0\) 的就基本解決了。

\(4\)\(3\) 的可以手玩一下 \(n=3\)(需要用到 \(-3\) 這個位置,腦洞有點大),然后嘗試推一下 \(n=7\),基本就出來了。

\(4\)\(2\) 的手玩 \(n=6\),不過我腦子不太好,看了下 CF 里的數據才知道怎么搞。

具體每一類的做法不太好說清楚,就不講了。

時間復雜度為 \(O(n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(201\)\(\text{Cumulative Code}\)\(\text{2020.11.01}\),以前見過)

題目大意:

有一個 \(k\) 層的滿二叉樹,結點從上到下從左到右編號,有 \(q\) 個詢問,每次給定 \(a,d,m\),求出二叉樹的 Prufer 序列 \(p_1,\ldots,p_{2^k-3}\) 中的以下元素和:\(\sum\limits_{i=1}^m p_{a+(i-1)d}\)

\(k\leq 30,\ \ q\leq 300\)


題解:

類似根號分治的一種分塊思路,將樹分成上 \(15\) 層和下面的部分,詢問時暴搜上 \(15\) 層,下面的部分通過預處理解決。

具體來說,遞歸問題分成兩個種類,分別是根結點有父親的子樹和根結點無父親的子樹,前者 Prufer 序列的刪點順序是左右中,后者是左中右,在前 \(15\) 層暴力模擬和遞歸即可。

當層數超過 \(15\) 時做一些預處理,我們提前處理好設根結點編號為 \(a\) 時深度為 \(k-15\) 的子樹的 Prufer 序列(其中的值都是 \(a\) 的線性函數),並在每個詢問時預處理公差為 \(d\) 的前綴部分和,遞歸時將根結點的 \(a\) 帶入就可以算出這個子樹里的和。

時間復雜度為 \(O(q2^{\frac{k}{2}})\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(217\)\(\text{Easy Reading}\)\(\text{2020.11.01}\),自己做出)

題目大意:

給定長度為 \(l\) 的字符串 \(S\) 和一個 \(n\times m\) 矩陣,矩陣中每個格子有黑有白,求出一個 \(S\) 的子串使得根據它可以畫出矩陣或報告無解,畫的規則如下:

  1. 首先畫筆落在任意一個格子上

  2. 然后從左到右遍歷這個子串,遇到 \(u,d,l,r\) 時畫筆就向上/下/左/右移動一格。

  3. 畫筆經過的位置都是黑的,其他位置都是白的。

\(l\leq 10^5,\ \ n\times m\leq 10^5\)


題解:

首先把 \(S\) 中所有的 \(u,d,l,r\) 提取出來,對矩陣進行二維哈希,這個哈希要支持平移,所以只要確定兩個數 \(x,y\),令黑色格子 \((i,j)\) 的哈希值為 \(x^iy^j\bmod P\) 就可以了。

接下來進行雙指針,維護一個畫出來恰好格子數和矩陣中格子數一樣的區間,動態維護 hash 值(可以用一個 multiset 來維護橫縱坐標最小值實現在判定時支持平移,再用一個 map 維護每個位置上畫了幾次,如果減到 \(0\) 次就會變成白色)。

時間復雜度為 \(O(l\log l+n\times m)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(218\)\(\text{Lunar Landscape}\)\(\text{2020.11.01}\),自己做出)

題目大意:

給定二維平面上 \(n\) 個邊平行於坐標軸或對角線平行於坐標軸的整點正方形,坐標范圍在 \([-1500,1500]\),求面積並。

\(n\leq 2\times 10^5\)


題解:

先處理邊平行坐標軸的正方形,二維差分最后前綴和回來就可以了。

對角線平行坐標軸的正方形是一樣的,另一個角度的二維差分。

最后每個格子可以統計出四個結果,分別是左上角左下角右上角右下角有沒有被覆蓋,如果有超過 \(2\) 個角被覆蓋那么就是完全覆蓋,如果有 \(2\) 個角被覆蓋且不是對角,那么就是被覆蓋了 \(0.75\) 個格子,如果只有一個角被覆蓋,那就就是被覆蓋了 \(0.5\) 個格子。

時間復雜度為 \(O(n+X^2)\),其中 \(X=3000\) 是坐標范圍。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(101\)\(\text{Correcting Curiosity}\)\(\text{2020.11.06}\),自己做出)

題目大意:

給定兩個字符串 \(S,T\),求出一個替換命令 \(a\to b\),其中 \(a,b\) 是字符串,使得從左到右尋找 \(S\)\(a\) 作為子串的若干次不相交的出現,每一次分別替換成 \(b\),最后能得到 \(T\),求出 \(|a|+|b|\) 最小的一組 \((a,b)\)

\(|S|,|T|\leq 2000\)


題解:

\(S\) 的每個子串哈希,離散化后用 vector 存儲每個哈希值的子串按照題目所述規則從左到右的每一次需要替換的位置。

然后枚舉 \(S\) 的子串 \(a\),根據 \(|T|-|S|=size\times \Delta len\),其中 \(size\) 是替換發生的次數,\(\Delta len\) 表示 \(|b|-|a|\),可以算出 \(\Delta len\),也就是可以算出對應的 \(b\),根據 \(a,b\)\(S,T\) 分成幾段,分別用哈希值檢驗每一段是不是都相等,同時如果每一次發生替換時 \(a\) 對應的 \(T\) 中的串也相等(都是 \(b\)),就說明 \((a,b)\) 是一組可行解。

時間復雜度為 \(O(|S|^2)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(167\)\(\text{Interactive Sort}\)\(\text{2020.11.10}\)

題目大意:

\(1,\ldots,n\) 中的奇數和偶數分成兩組並打亂順序,得到 \(o,e\) 兩數組,每次交互可以詢問 \(o_i\)\(e_j\) 的大小關系,你需要用不超過 \(3\times 10^5\) 個問題求出 \(o,e\) 兩數組,數據隨機生成。

\(n\leq 10^4\)


題解:

首先用 \(e_1\) 和每一個 \(o_i\) 問一次,可以把 \(o_i\) 分出兩份並求出 \(e_1\),然后再是 \(e_2\),兩個數問完相當於把 \(o_i\) 分成三份,依此類推。

問每一個 \(e_i\) 時,首先在當前分出的每一段 \(o_i\) 中二分找到它可能輸入哪一段(或兩段),然后將這一段或兩段中的 \(o_i\) 都問一遍,就可以找到確切位置並多分一份 \(o_i\) 出來了。

在隨機數據情況下,詢問 \(O(n\log n)\) 次。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(109\)\(\text{Knapsack Cryptosystem}\)\(\text{2020.11.11}\)

題目大意:

有一個未知數組 \(a_{1\ldots n}\),滿足 \(\sum\limits_{i=1}^{k-1} a_i< a_k\),且 \(\sum\limits_{i=1}^n a_i< q=2^64\),並有一個奇數 \(r\),令 \(b_i=r\times a_i\),對於一個 \(n\)\(0,1\)\(S\),定義其加密結果為 \(\sum\limits_{S_i=1} b_i \bmod q\),請你對給定的加密結果解密。

\(n\leq 64\)


題解:

看上去是 Not P 的,考慮進行數據分治,復雜度有機會攤成 \(O(2^{\frac{n}{3}})\)

  1. \(n\leq 42\),直接折半搜索,復雜度 \(O(2^{\frac{n}{2}})\)

  2. \(42<n\leq 64\),考慮到 \(q>\sum\limits_{i=1}^n a_i>2^{n-1}\times a_1\),所以其實 \(a_1\leq 2^{64-n}\),那么我們可以考慮枚舉 \(a_1\),當 \(a_1\) 確定時我們可以再考慮確定 \(r\),根據 \(a_1\)\(b_1\) 我們可以確定 \(r\) 的某些位(准確地來說,是去掉 \(a_1,b_1\) 的公共后綴 \(0\) 后剩余的位數),剩下 \(r\) 中未確定的位再暴力枚舉就可以了,因為這個未確定位數就等於 \(a_1\) 后綴 \(0\) 的個數,求和后不影響 \(O(2^{64-n})\) 的復雜度。

二者綜合,可以得到一個復雜度不高於 \(O(2^{\frac{n}{3}})\) 的做法。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(226\)\(\text{Maze Reduction}\)\(\text{2020.11.11}\)

題目大意:

給定 \(n\) 個結點的無向圖,每個點的所有相關邊形成一個有向環(即可以區分正逆和距離),如果從兩個不同的結點出發,無論如何行動都無法辨別出自己從哪里出發,則稱它們等效相同,按此標准求出所有等價類。

\(n\leq 100\)


題解:

數據比較厲害,為了搞掉一些卡常毒瘤數據,所以我先特判了一下,如果所有點度數相同,直接返回所有點都等價。

可以設計一種簡單的 DP,假想我們可能在兩個不同的房間,並且上一步分別從某個房間走來,那么需要知道的信息還有:上一步分別是從各自的順時針第幾個邊走進來的,初步可以想到 \(dp(i,j,k,l)\) 表示分別在 \(i,k\),分別是從第 \(j,l\) 條邊走進來,能否分辨。但是考慮到 \(dp(i,j,k,l)\)\(dp(i,j+x,k,l+x)\) 其實等價,所以可以省掉一維,只用 \(dp(i,j,k)\),而令 \(l=1\)

但是這樣不太好轉移,我們不妨加一個步數的限制,即 \(dp(i,j,k,x)\) 表示在上述的 \((i,j,k)\) 狀態下,走 \(x\) 步以內能否分辨,這樣我們便能從 \(x-1\) 的狀態轉移過來了。

這里的 \(x\) 上限我設成了 \(50\),基本應該是沒有問題的。

時間復雜度為 \(O(nm^2\times X)\),其中 \(m\) 是邊數,\(X=50\) 是步數上限,這種寫法非常卡。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(106\)\(\text{Binary vs Decimal}\)\(\text{2020.11.11}\)

題目大意:

求出第 \(n\) 小的滿足其十進制表示是其二進制表示的后綴的數。

\(n\leq 10^4\)


題解:

寫個高精度,然后搞個 \(\text{priority_queue}\) 暴搜即可,每次取出一個滿足條件的數就在前面加 \(0\)\(1\) 都試試,可以發現答案不會超過 \(200\) 位。

時間復雜度不明。

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(159\)\(\text{Mole Tunnels}\)\(\text{2020.11.11}\)

題目大意:

給定 \(n\) 個點的完全二叉樹,每個點有最多能容納鼴鼠的上限,現在依次來了 \(m\) 只鼴鼠,每個鼴鼠有個初始位置,對於每個 \(i\leq m\) 求出:給前 \(i\) 個鼴鼠分別安排到一個點,不超過每個點容納上限時,所有鼴鼠移動距離和的最小值。

\(n,m\leq 10^5\)


題解:

用模擬費用流來考慮,然后可以用可回退貪心來解決。

每次給新來的鼴鼠找一個最近的可以容納的點然后塞進去,隨后將這條路徑上邊權取反即可。

可以用一個類似 DP 數組一樣的東西維護每個點子樹內最近的可以容納鼴鼠的點,由於是完全二叉樹,所以詢問可以暴力跳祖先。

時間復雜度為 \(O(m\log n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(251\)\(\text{Can't stop playing}\)\(\text{2020.11.11}\)

題目大意:

依次給定 \(n\) 個長度為 \(2\) 的非負整數冪次的方塊,你可以依次選擇將它們放在當前序列的最左邊或最右邊,每當兩個相鄰方塊長度相同時就會合成一個長度是兩倍的大方塊,求是否可以使得最終結果合成一塊。

\(nL\leq 5\times 10^8\),其中 \(L\) 是方塊總長,不超過 \(2^13\)


題解:

如果想要最后合成一塊,那么任何時候游戲序列必須是單峰的(否則位於谷中的方塊永遠無法和兩邊合並),所以抓過狀態數不過 \(2^{26}\) 種,然后我們又發現合成操作不影響長度總和,所以假設前 \(i\) 個方塊長度和為 \(S_i\),那么我們只需要記錄當前序列前面遞增那一部分的長度和 \(S\),用 \(S_i-S\) 就得到了后面那部分遞減的長度和,因此狀態數又降到了 \(2^{13}\)

然后分幾類轉移即可,特別注意遞增部分或遞減部分為空的情況,同時如果 \(S_n\) 不是 \(2\) 的冪次那么答案顯然是否。

時間復雜度為 \(O(nL)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(169\)\(\text{Virus synthesis}\)\(\text{2020.11.11}\)

題目大意:

給定由 \(\texttt{A,C,G,T}\) 構成的長度為 \(n\) 的字符串,問最少用幾步可以由空串構造出來,每一步可以:

  1. 在開頭或末尾加一個字符;

  2. 將當前串翻轉並接在當前串的前面或后面。

\(n\leq 3\times 10^7\)


題解:

考慮最后一次翻轉,形成的一定是一個回文串,所以我們不妨對字符串的所有本質不同回文串進行 DP。

在 PAM 上,設回文串 \(S\) 的最長回文真后綴為 \(S_1\),最長的長度不超過一半的回文串為 \(S_2\),那么 \(S\) 要么由 \(S_1\) 加字符得到,要么由 \(S_2\) 加字符並翻轉拼接得到,而求這兩個東西是 PAM 標配,所以可以直接 DP 出結果。

枚舉一下最后一次翻轉形成的回文串並看一下后面還要幾次操作,就可以得到答案。

時間復雜度為 \(O(n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(127\)\(\text{Lost Logic}\)\(\text{2020.11.11}\)

題目大意:

給定三個長度為 \(n\)\(0,1\) 串,構造一組條件數不超過 \(500\) 的 2-SAT 條件使得三個串是唯一的三組解,或報告無解。

\(n\leq 50\)


題解:

如果某一位上三個串都是 \(0\) 或者都是 \(1\),那么這一位相當於沒用,直接令它為 \(0\)\(1\) 即可。

否則,這一位一定是兩個一樣,另外一個不同,那么我們就把它划進這兩個一樣的串構成的一個等價類里,於是會有三個等價類(在 \(1,2\) 中一樣,在 \(1,3\) 中一樣,在 \(2,3\) 中一樣),於是我們令每個等價類中的情況唯一。

最后我們還要判定一下,如果每一位都取那個兩個相同的數字,得到的串是否屬於一開始的三個串,如果不屬於那么無解(無法構造條件使它不滿足),否則剛才已經構造出了合法解。

時間復雜度為 \(O(n)\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(143\)\(\text{Jump}\)\(\text{2020.11.11}\)

題目大意:

你要猜一個長度為偶數 \(n\)\(0,1\)\(S\),每次詢問可以給出一個長度為 \(n\)\(0,1\)\(T\),如果 \(S\)\(T\) 中對應相同的位數恰好為 \(n\)\(\dfrac{n}{2}\) 的話就會返回這個值,否則會返回 \(0\),用不超過 \(n+500\) 次操作得到 \(S\)

\(n\leq 1000\)


題解:

考慮如果已經得到一個能問出 \(\dfrac{n}{2}\)\(T\),如何得到答案。

如果將 \(T\) 中的 \(i,j\) 兩位分別反轉,得到 \(T'\),詢問 \(T'\),如果得到 \(0\),說明 \(T\) 里面這兩位和 \(S\) 都相同或都不同,如果得到 \(\dfrac{n}{2}\) 就說明這兩位有一位相同而另一位不同,令 \(i=1\),問 \(n-1\) 次就可以知道:當第 \(1\) 位與 \(S\) 相同或不同時,每一位與 \(S\) 相同或不同。

於是候選的 \(S\) 只剩兩個,都問一次就知道答案了。

問題在於如何找出這個 \(T\),然而這個問題的答案是顯然的:隨機問,似乎是因為 \(\lim\limits_{n\to \infty} \dfrac{\binom n {\frac{n}{2}}}{2^n}=\sqrt n\),所以只要大概 \(50\) 次以內就可以得到這個 \(T\)

詢問次數大約為 \(n+\sqrt n\)

\(\rule[0pt]{14.3cm}{0.1em}\)

#\(210\)\(\text{Sensor Network}\)\(\text{2020.11.12}\)

題目大意:

給定 \(n\) 個平面上的點,兩點距離 \(\leq d\) 就連邊,求最大團。

\(n\leq 100\)


題解:

解法一:當成普通圖,random_shuffle 貪心加點或者搞點暴搜,可以通過。

解法二:靠譜多項式復雜度解法:

枚舉兩個點,令它們的距離 \(d_0\) 是團中最大距離,那么團中剩余的點的范圍就是以它們連線段為公共底邊的兩個等邊三角形,可以發現一個三角形內的點兩兩都有連邊,所以要求這個圖的最大團,不妨取反圖求獨立集,這樣只有分屬兩個三角形的點可能有邊,也就是一個二分圖,做一遍最大匹配即可。

時間復雜度可做到 \(O(n^4)\) 左右。


免責聲明!

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



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