# NHSPC 決賽 2021~2022 ## 2022 [題目](https://nhspc2022.twpca.org/release/problems/problems.pdf) ### B. 自行車歸位 (bicycle) 有$n$個腳踏車,$m$個空位,給定一維座標,問把所有腳踏車都移到空位的最小總距離。 :::spoiler 解法: 從範例開始觀察,可以發現當$m=n$時,照順序由小到大依序歸還必是一組最佳解。也不難推出,對於所有情形,必有一組最佳解為 腳踏車座標越大,歸還座標越大。 為了簡化問題,我們將所有的$a<b<x<y$ $a\rightarrow x, b\rightarrow y$換為$a\rightarrow y, b\rightarrow x$,即所有的連線皆完全包含或不相交。 一輛腳踏車 b 只會有兩個可能被歸還的地方: $l_b$:在$b$左邊,滿足$[l_b, b]$間腳踏車與空格數量相等,座標最大的空位 $r_b$:在$b$右邊,滿足$[b, r_b]$間腳踏車與空格數量相等,座標最小的空位 可利用stack在線性時間得出所有可能的連線,然後再做一次dp就好了。 ::: ### C. 卡牌 (card) 每一回合從未選卡牌序列的最左邊或最右邊選一張卡片。隨著每回合減少了一張卡牌,剩餘卡牌的得分就會各加上其最初得分的十分之一,也就是第$k$回合結束時還未選的卡牌的得分 會為最初得分的$1+0.1k$倍。在最佳的選卡策略時,給定的卡牌序列最多可以獲得多少總得分? 保證初始分數皆為10的倍數。 * $n\leq 1000$ :::spoiler 解法: 定義dp[i][j]為,序列剩下[i,j]時,目前可獲得的最大分數,有可能從dp[i][j+1] or dp[i-1][j]轉移。 ```cpp= for(int i=0;i<n;i++){ for(int j=n-1;j>=i;j--){ if(i>0) dp[i][j]=max(dp[i][j],dp[i-1][j]+v[i-1]*(10+n-1-j+i-1)/10); if(j<n-1) dp[i][j]=max(dp[i][j],dp[i][j+1]+v[j+1]*(10+n-1-j-1+i)/10); } } ``` 最後答案即為 ```cpp= for(int i=0;i<n;i++) ans=max(ans,dp[i][i]+v[i]*(10+n-1)/10); ``` ::: ### D. 文字編輯器 (editor) 有以下規則: • 單獨一個$x$是一個合法表達式。 • 如果$e$是合法表達式,則$|e|$也是合法表達式。例如:$x$是合法表達式,所以$|x|$也是合法表 達式。 • 如果$e$是合法表達式,則$[e]$也是合法表達式。例如:$x$是合法表達式,所以$[x]$也是合法表 達式。 • 如果$e1$和$e2$是合法表達式,則$e1+e2$也是合法表達式。例如:$|x|$和$[x]$是合法表達式,所以 $|x|+[x]$也是合法表達式。 現給一個只由"$x$"、"$|$"、"$+$"組成的字串,要把恰一個"$|$"改成"$+$",並把剩下的"$|$"都改成"$[$"或"$]$"。 :::spoiler 解法: 先觀察到一件事:"$[$"和"$]$"必在"$x$"、"$+$"之間,連在一起的一定都同方向,"$x$"左邊必為左括號,右邊必為右括號。 先找$+$可能放的區間(必在兩個"$x$"之間),窮舉放的位置,如果左邊的和($[$為1,$]$為-1)+右邊的和=$0$,就是合法的。 ::: ### E. 齒輪組 (gears) 齒輪彼此接合或帶動,問最後一個齒輪的方向和轉速。 :::spoiler 解法: 直接線性做就好。 ::: ### F. 百萬刮刮樂 (scratchcard) 有$n$張卡片,每張卡片$i$上面,由上至下依序有四筆數字$W_i, A_i, B_i, C_i$,其中$W_i\in \{ 1e6, 2e6, 3e6\}$。 抽出兩張相異卡片$x$和$y$,如果這兩張卡片上面的數字滿足以下條件,那麼中獎金額就是$K=W_x+W_y$,否則就沒有中獎。 條件:兩張卡片的$A, B, C$值相加皆須大於等於$K$ 問有可能的$K$有多少種。 * $n\leq 2e5$ * $A_i, B_i, C_i\leq 6\times 10^6$ :::spoiler 解法: $K$只有可能是$2e6, 3e6, 4e6, 5e6, 6e6$,所以題目變成:給定$K$,是否存在兩張刮刮樂滿足條件 若只有一個條件(如$A$)可以先排序後用簡單的用雙指標算對於每一個$i$,有那些$j>i$滿足$A_i+A_j\geq K$。 現在要再加入兩個條件,可以想成維護一個資料結構,檢查完$i$要檢查$i+1$時,把可以和$i$配但不能和$i+1$配的$j$拿掉。 --- 現在的問題是:要如何建立一個資料結構可以查詢是否有$j$滿足$B_j\geq K-B_i$ 且$C_j\geq K-C_i$,並且可以支援刪除。 **對B的值域開線段樹**,存C的值,查詢[$K-B_i, B_{max}$]中 C的最大值是否大於等於$K-C_i$。 另外要注意因為$B$有可能重複,每個葉節點裡面要再放個multiset儲存該$B$值對應的$C$值。 ::: ### G. 算樹 (tree) 給一棵樹的每個節點的度數,求可能的[Prüfer序列](https://zh.wikipedia.org/zh-tw/%E6%99%AE%E5%90%95%E5%BC%97%E5%BA%8F%E5%88%97)中,字典序第$k$小的。 :::spoiler 解法: 先觀察(或通靈)出一個性質:一個點在序列中出現的次數恰為 該點的度數$-1$ ,且任何序列都可以構造出一棵樹。 因此用排列組合算出一個序列的排列數,然後再依次算第一位、第二位該放哪個數字。往下一個位數做的時候不需要再重新算一次排列數,可以直接由上一個位數轉移。詳細如下: 定義數字$i$在序列中出現$a_i$次 所有的排列數為 $$ K := \frac{(a_1+n_2+\ldots+a_n)!}{a_1! a_2! \ldots a_n!} $$ 以$i$為開頭的序列個數為: $$ K_i := \frac{(a_1+\ldots+a_n -1)!}{a_1! \ldots (a_i-1)! \ldots a_n!} = K\frac{a_i}{a_1+\ldots+a_n} $$ ::: ### I. 聖誕燈飾 (xmas) 有一組$n$顆$m$色燈泡的燈飾。這些燈泡排成一列,由左至右編號為$1, 2\cdots n$。燈泡的顏色是可變的,編號為$1, 2\cdots m$。若一顆燈泡的顏色為$i$,其中$i\leq m$,則改變顏色會變為$i+1$;若一顆燈泡的顏色為$m$,則改變顏色會變回$1$。 每顆燈泡下皆有一個按鈕可以改變燈飾整體的顏色,按下燈泡$k$的按鈕,會一齊改變燈泡$k, 2k, 3k\cdots$的顏色。例按下燈泡 2的按鈕,只能使編號為偶數的燈泡變色。已知初始 n 顆燈泡的顏色分別為$a_1, a_2\cdots a_n$,小千打算按下$\zeta _i$次燈泡$i$的按鈕,使得最後的顏色變成 $b_1, b_2 \cdots b_n$,請幫她找出滿足條件的$\zeta _1, \zeta _2\cdots \zeta _n$。若有多組滿足條件,請找出字典序最小的那組;若不存在這樣的方案,請輸出$−1$。 :::spoiler 解法: 先把問題轉換為以下數學式: $$ \begin{cases} \begin{aligned} \zeta _1&\equiv b_1-a_1\\ \zeta _1+\zeta _2&\equiv b_2-a_2\\ \zeta _1+\zeta _3&\equiv b_3-a_3\\ \zeta _1+\zeta _2+\zeta _4&\equiv b_4-a_4\\ \vdots\\ \Sigma _{d|n} \zeta _d&\equiv b_n-a_n \end{aligned} \end{cases} mod(m) $$ 題目要求字典序最小,因此$\zeta _1=b_1-a_1$,那麼$\zeta _2$就可以代入$\zeta _1$求出來,以此類推。 因此作法如下: 對於每個$i$,將第$2i, 3i\cdots$條算式都減掉$\zeta _i$,就能保證走到每一條算式時都只會剩下一項。 ::: ## 2021 [題目](https://tioj.ck.tp.edu.tw/pmisc/nhspc110.pdf) ### [A. 髮廊服務優化問題(barbershop)](https://tioj.ck.tp.edu.tw/problems/2251) 給定$n$位客人需要的服務時間,問最小的總等待時間。 * $n\leq 200$ :::spoiler 解法: 排序後greedy地從最大的開始。 ::: ### [B. 校園公車 (bus)](https://tioj.ck.tp.edu.tw/problems/2252) 有一條由$n$個線段組成的折線,給一個點$O$,問此點到折線的最短距離。 :::spoiler 解法: 窮舉每一條線段,最後取min。 先用畢氏定理判斷點$O$和線段兩端圍成的三角形是否為鈍角三角形。 若是,則最近的點為線段兩端點之一。 若非,用向量外積算出三角形面積,然後除以線段長度,即為點到線段最短距離。 [向量寫法](https://hackmd.io/@Viecon-342524/HJLBoymz2#%E5%90%91%E9%87%8F) ::: ### [D. 汽車不再繞圈圈(car)](https://tioj.ck.tp.edu.tw/problems/2254) 給一張有邊權的有向圖,管理員有權限值$P$可以將任意條邊權小於等於$P$的邊翻轉方向,使得圖中不存在環。問最小的$P$為何,並輸出一種翻轉方案。 :::spoiler 解法: 對排序後的邊權二分搜答案(因為$P$一定等於某一個邊權),若要檢查$x$,可以先把所有邊權小於等於$x$的邊都刪掉,檢查剩下的圖是否有環,若剩下的圖沒有環,那麼加任意條可以改變方向的邊,一定有辦法構造出一種方案。就可以找出最小的$P$了。 找出$P$後,如何找出翻轉方案? 對剩下的圖做[拓撲排序](https://hackmd.io/@Viecon-342524/Hk-K-vw8j#%E6%8B%93%E6%92%B2%E6%8E%92%E5%BA%8F),讓加入的邊符合這個順序。 因為加入符合順序的邊不會改變原本的拓樸順序,而只要所有點都在拓樸排序內,就一定不會有環。 ::: ### [F. 挑水果 (fruit)](https://tioj.ck.tp.edu.tw/problems/2256) 有$c$種水果和$c$個城市,在第$i$個城市可以選擇是否要以每顆$S_i$元的價格將**前$i$種水果全部卸貨**,且對於種類$j$,能賣出$r_{i,j}$顆給消費者,另外到達第$i$城市時船上的每顆水果要花費$P_i$元(不論種類),現給預算$T$,問在哪些城市卸貨能使賣出的水果最多。 :::spoiler 解法: 令`dp[i][j]`為最後一次在城市$i$卸貨,目前銷售量為$j$時所花的最小成本。 dp[這一次卸貨的地方][目前總共的銷售量]=dp[枚舉上一次卸貨的地方][上一次的銷售量]+船上的水果量$\times$這一段的總$P$+這個地方的$S$$\times$這一次的卸貨量 $$ dp[i][j]=\mathop{\min}_{0\leq k<i} (dp[k][j-\sum _{x=k+1} ^i r_{i,x}]+\sum _{x=k+1} ^c n_{x} \times \sum _{x=k+1} ^i P_x+S_i\times \sum _{x=k+1} ^i n_x) $$ sigma 可以用前綴和處理。然後算答案時記得加上船上剩餘的水果載到終點的運費。 最後答案即為不超過$T$的答案中最大的$j$ ::: ### [G. 鳳梨關稅 (pineapple)](https://tioj.ck.tp.edu.tw/problems/2257) 給一個樹,支援兩種操作: 1. 將一條邊的權重從$1$變為$0$ 2. 問從根節點到某個節點的權重總和 :::spoiler 解法: [樹壓平](https://hackmd.io/@Viecon-342524/r1qfzJEm3#%E6%A8%B9%E5%A3%93%E5%B9%B3)後就可以套BIT或線段樹了。 ::: ### [I. 鐵路鋪設 (rail)](https://tioj.ck.tp.edu.tw/problems/2259) 有一個$2*L$的矩形,有多少種鋪鐵路的方式? 規則: 每個格子只有一條路線,路線皆須要是環,每條路線至多只有一條是斜的 ![](https://hackmd.io/_uploads/Sk8vTSPrh.png) :::spoiler 解法: 這題有滿多種想法的,這裡提供一種。 假設以$A_L$表示$L$的答案,且定義$A_0=1, A_1=0$。 有$A_{L-1}$種情況可從$L-1$往右延伸一格: ![](https://hackmd.io/_uploads/Hye-CIwHn.png) --- 那麼有哪些情況不能從$L-1$延伸? 最右邊為這三種情形: ![](https://hackmd.io/_uploads/HJJMlDvS2.png) 針對第三種情形,方法數就等同於$A_{L-2}$。 針對第一種,可以枚舉倒數第二個環的大小,以下以$L=5$為例。 ![](https://hackmd.io/_uploads/BJ4yZvvBn.png) ![](https://hackmd.io/_uploads/rJei7-DDrh.png) ![](https://hackmd.io/_uploads/BkrvbwDrn.png) 可以觀察出有$A_{L-3}+A_{L-4}+\cdots +A_0$種 且第二種和第一種一樣多。 把上面全部加起來可以得到: $$ \begin{aligned} A_L&=A_{L-1}+A_{L-2}+2(A_{L-3}+A_{L-4}+\cdots +A_{0})\\ &=A_{L-1}+A_{L-3}+A_{L-2}+A_{L-3}+2(A_{L-4}+A_{L-5}+\cdots +A_0)\\ &=A_{L-1}+A_{L-3}+A_{L-1}\\ &=2A_{L-1}+A_{L-3} \end{aligned} $$ 這個很漂亮的算式。 最後再套進[矩陣快速冪](https://hackmd.io/MGfghW7KQu2MdWTOzM6WcQ?view#%E7%9F%A9%E9%99%A3%E5%BF%AB%E9%80%9F%E5%86%AA)就好了 ::: ## 參考 https://nhspc2022.twpca.org/editorial/editorial