Google Code Jam 2022 Round1A
Double or One Thing
做法1
假設當前字元比下一個字元小,那麼複製一遍肯定更優。
假設當前字元比下一個字元大,那麼複製一遍肯定更優。
假設當前字元和下一個字元相等,那麼就看下一個不等的字元的大小,更大就這一串全複製,不然就全不復制。
做法2
從後面開始貪心,每次看是否複製,貪心的選小的。
Equal Sum
比賽的時候想到了利用二進位制來構造任何數,但是就是差一步。
首先,把\(\{2^i | 0\le i \le 29\}\)共30個數加入\(A\),剩下70個數隨意。
然後再輸入進來100個數。
考慮先將後170個數分成兩個集合\(A\)和\(B\),記\(S(x)\)表示集合\(x\)
後面考慮用2的冪次來消除差值。現在需要劃分的200個數都確定了,他們的和能確定,最後兩個集合相等,那麼其中一個集合的和\(S\)也確定了。
現在考慮把較小的那個集合,假設它的元素和為\(S^{\prime}\)吧,用2的冪次補到\(S\)。易得\(S\)的取值介於\(S(A)\)和\(S(B)\)之間,所以\(d = S - S^{\prime}\)的值會小於\(10^9。然後根據\)d$的二進位制可以輕易做到。
Weightlifting
比賽的時候沒想出來,寫了一小時爆搜都沒恰到部分分。
對於一個區間內的訓練(exercise),可以先將區間內共有的負重(weights)加入棧中,對於該區間而言加入的順序不影響結果,等這個區間都處理完了之後,再依次出棧。
對於一個區間,可以將其拆分為兩個部分,先做左區間,在做右區間,對於每一個區間,都利用上述觀察,這樣問題就可以通過一個遞迴的過程解決,然後結合記憶話搜尋或者說區間DP,就可以解覺問題,複雜度大概在立方級別。
具體而言就是,記\(c(l, r)\)為區間\([l,r]\)中所有訓練共有的負重數量,\(dp(1, n)\)為區間\([l, r]\)除了共有的負重之外還需要的代價。那麼最後的答案就是\(dp(1, E) + 2 c(1, E)\)