1. 程式人生 > 其它 >【題解】NOIP 2020 移球遊戲 / 微信步數

【題解】NOIP 2020 移球遊戲 / 微信步數

對比後可以發現 t4 部分分好拿,但是最後 \(20\) 分程式碼很複雜,考場上不太能搞。t3 的部分分給的沒有 t4 猛,但是 t3 題目難度整體小於 t4,基本屬於套路分治。

T3

首先考慮 \(n=2\) :考慮先將所有的柱子整理為黑上白下,然後最後通過空柱子拼湊得解。

假設一號柱子有 \(k\) 個黑球,那麼:移動二號柱子的 \(k\) 個球至三號柱子,將一號柱子的黑球移到二號柱,白球移到三號柱,最後先取回三號柱的白球再取回二號柱的黑球,操作次數上限為 \(4m\)

知道做 \(n=2\) 後就不難得到一般做法了,具體可以考慮分治,再每一層中,先用上述演算法整理柱子(消耗 \(4mn\)

步),然後考慮怎麼拼湊。

隨便取兩個柱子,如果加起來黑色球多的話,那麼可以先倒裝一個柱子,將另一個柱子的黑白分開後,再將倒裝柱子裝回去;如果加起來白色球多的話,那麼先取所有的黑色球,將剩下的兩個白色儘可能合併後再把黑色球裝回來。無論是哪種情況,單次消耗的步數都是 \(3m\)

那麼一層消耗的總步數的理論上限為 \(7nm\),故總操作次數理論上限為 \(7nm\log n\),消耗的步數在題目限制的邊上。

程式碼:提交記錄 #1241578 - LibreOJ

T4

先考慮前 \(80\) 分,只需要考慮走出去的時候是哪一維走出去了即可,列舉這一維,然後看其他維有多少選擇。

具體做法就是處理出 \(t(i,j)\)

表示第 \(i\) 維第 \(j\) 個位置走多久走出去,然後將 \(\sum w_i\) 個元素按照時間排序後就能線性做了。

接下來考慮滿分做法,注意到對於 \(i\)\(t(i,j)\) 是一個先單調不減,後單調不增的函式。這兩部分,一部分是在第一輪內就直接出去了,這樣的位置個數是 \(O(n)\) 且需要的時間不超過 \(n\),暴力處理;另一部分是走了超過 \(n\) 步的,讓我們來分析一下:

\(p_{j}<n\) 表示向著要走出的方向,從起點開始最遠走了 \(j\) 步的時間,如果單輪走不了這麼遠就不定義 \(p_j\) 。注意到,因為一輪走的最遠的距離並不代表一輪結束後到達的距離,所以,因為另一部分可以表示為 \(t+kn,(t<n,k\geq 1)\)

,對於 \(k=1\) 的週期,因為不需要考慮上一輪的最遠距離和結束距離的偏差,所以有可能和 \(k>1\) 的週期不一樣,但是對於 \(k>1\) 的週期,因為一定需要考慮上一輪最遠距離和結束距離的偏差,所以一定一樣。

也就是說,一個維度只需要處理 \(O(n)\) 個位置的值,剩下的位置的值都是一個一個長度不超過 \(n\) 的週期不斷迴圈的,並且剩下的位置的值一定都大於 \(2n\),前面處理的位置一定都不超過 \(2n\) ,所以可以直接分成兩部分做。

前一部分按照 \(80\) 分做法做即可,後一部分是簡單的計數問題。

程式碼:口胡,不想實現。