8.6 模擬賽
蓋世計劃--C班--濰坊營--8月6日 - 比賽 - 夢熊聯盟 (mna.wang)
蓋世計劃--C班--濰坊營--8月6日【訂正】 - 比賽 - 夢熊聯盟 (mna.wang)
太久沒打真實的模擬賽了,今天有些不適應【】
時間是 8.6 的 8:00~12:00,時間分配出了大問題。主要問題是 T3 的 5k 線段樹調起來困難無比。最後也沒調完。導致暴力分少了 100 多【】
賽後發現掛的地方是一個區域性變數沒賦初值【】
A 線段
一開始沒看懂題。過了很長時間後看懂了一點,覺得 \(n \le 5\) 的 dfs 很快就能寫完就沒管這題。此時正在寫 T3 就沒管它。快結束時想寫這題暴力又忘了題意是啥了【】。
\(0+100\)。
題意
數軸上有 \(n\) 個點,構成了 \(\frac{n(n+1)}2\) 個線段。令所有線段為全集。問有多少子集,滿足這個子集內的線段,在兩兩不交的情況下能選出的最多線段數恰好為 \(k\)。\(k \le n \le 500\)。
做法
如果暴力 dfs,那麼 check 的做法是經典貪心。即將所有線段按照右端點排序,然後順次判斷能不能選這條線段。見 AcWing 908.。
資料範圍不大,考慮狠狠地 DP。
設 \(f(i, j)\) 表示當前貪心得到的最大右端點的位置 \(\le i\),且最優策略中選擇的線段數量為 \(j\) 時的總方案數。
或者,\(f(i, j)\) 即有多少個原題的答案的線段集合,使得這個集合的最優選擇中最靠右的線段的右端點 \(\le i\),且最優方案選擇的線段數量為 \(j\)。
轉移。列舉倒數第二大的最優選擇中的線段的右端點 \(p\)。我們考慮線段 \([l, r]\)(\(l \le r \le i\)):
- 若 \(r \le p\):那麼這條線段在 \(f(p, j - 1)\) 中已經被計算過了。
- 若 \(l \le p\) 且 \(p < r < i\):這條線段一定不在 \(f(i, j)\) 的最優選擇中。所以這樣的線段可有可無,方案是 \(2^{p (i-p-1)}\)。
- 若 \(p \le l < r < i\):這條線段如果存在,就不滿足「最優選擇中最靠右的線段的右端點為 \(i\)」這個條件。所以這樣線段不能出現。
- 若 \(l \le p\) 且 \(r = i\):這條線段一定不在 \(f(i, j)\) 的最優選擇中。所以這樣的線段可有可無,方案是 \(2^p\)。
- 若 \(p < l\) 且 \(r = i\):這條線段可能是 \(f(i, j)\) 狀態中所說的「最優選擇中最靠右的線段的右端點為 \(i\)」的線段,但是這條線段只能有一條,而剩下的線段可有可無。方案是 \((2^{i-p} - 1)\)。
綜上轉移:
初始化:
- \(f(i, 0)\):表示最優方案選擇的線段數量為 \(0\)。顯然只用空集一個,答案為 \(1\)。
- \(f(0, i)\):表示線段右端點為 \(0\)。仍然只用空集一個,答案為 \(1\)。
快速冪是過不掉的。我們考慮預處理一些 \(2\) 的冪:
- \(2^p\),\(2^{i-p}\):線性遞推。
- \(2^{p(i-p-1)}\):設 \(g_{i, j} = 2^{ij}\),那麼轉移 \(g_{i, j} = g_{i - 1, j} \times 2^j\) 或 \(g_{i, j} = g_{i, j - 1} \times 2^i\)。
B 計算
這場比賽開的第一道題。因為第一眼,原!
顯然這兩道題不一樣【】
漲了很多見識,數論題也是可以 DP 的!
\(40+100\)。
題意
給定 \(k\) 個兩兩互質的正整數,求 \(1 \sim n\) 中有多少數不能被任意一個數整除。
做法
「多少數不能被任意一個數整除」= $n - $ 「多少數能被任意一個數整除」。
考慮 DP。設 \(f(n, k)\) 表示有多少個 \(1 \sim n\) 的數,能被 \(a_1,a_2\dots a_k\) 中的任意一個數整除。
很妙的轉移!
其中,\(\lfloor n / a_k\rfloor\) 表示 \(1 \sim n\) 中能被 \(a_k\) 整除的數的個數,\(f(n, k - 1)\) 表示 \(1 \sim n\) 中能被 \(a_1\dots a_{k-1}\) 整除的數的個數。
顯然這兩個集合可能有交,即 \(1 \sim n\) 中既能被 \(a_k\) 整除,又能被 \(a_1 \dots a_{k-1}\) 中任意一個數整除的數。
如果一個數 \(x\) 是這兩個集合的交,那麼 \(\frac x{a_k}\) 一定能被 \(a_1 \dots a_{k-1}\) 中任意一個數整除。那麼 \(\frac x{a_k}\) 的數量為 \(f(\frac x{a_k},k-1)\)。因為 \(x\) 和 \(\frac x{a_k}\) 一一對應,所以 \(x\) 的數量也是 \(f(\frac x{a_k},k-1)\)。
直接用 (u)map 轉移空間複雜度會爆。最佳化方案有兩種:
方法一:整除分塊。
前排提醒,這種做法在時間上被卡常樂【】
對於每一個有效的狀態 \(f(i, j)\),這個 \(i\) 一定是由給定的 \(n\) 開始,不斷除以某個 \(a_k\) 下取整得到的。根據 知識 我們得知這樣的 \(i\) 的數量是根號級別的。
因此我們可以雙指標得到 \(n\) 除以某個數下取整可能的得到的值(如上所述,數量是根號級別的),將其離散化即可。
離散化後轉移可以雙指標,一個指向 \(n\),一個指向 \(\lfloor n / a_k\rfloor\)。
而且這個狀態的第二維可以滾動最佳化。空間複雜度做到了根號。
後排提醒,這種做法在時間上被卡常樂【】
方法二:暴力 + 記憶化。
我們設一個閾值 \(B\),然後記憶化轉移。對於狀態 \(f(i, j)\) 若 \(i < B\) 則用陣列記憶化。否則直接轉移不記憶了。這裡我取的 \(B = 10^6\)。不難(?)證明這樣的複雜度是正確的。
極其相似的題有 CF1806E,比較相似的題有 ABC365G。
C 球
罪魁禍首。
這是一個難想+難寫+難調的做法。最終程式碼 5KB。
\(0+100\)。
題意
太長了回去看吧。
做法
我們給每個空隙一個屬性:
其中 \(s_i\) 表示與空襲 \(i\) 相鄰的兩個邊的狀態。
模擬一下可以發現,如果要反轉邊 \([l, r]\),首先我們可以分類討論出 \(a_l\) 和 \(a_{r+1}\) 的變化,其次 \(a_{l+1}\dots a_r\) 都會變成它的相反數。
考慮詢問。如果在兩個相鄰的山峰(\(a_i=+\infty,s_i = \texttt{/\\}\))間扔球,那麼這些球都有相同的歸宿。所以答案為 \([l-1, r]\) 中相鄰的兩個 \(+\infty\) 的下標差的最大值。
寫一顆 5KB 線段樹即可。
在查詢之前我們可以先將 \(a_{l-1}\) 和 \(a_r\) 設成 \(+\infty\)。顯然現在我不知道當時我這麼寫的原因了,反正這樣寫能燒掉很多特判。
D 數列
神秘題,數學推導沒聽懂。
\(0+40\)。
說一下 40 分暴力:對於每個 \(k \in [1, 100],n\in[1,10^5]\) 預處理一張答案表。預處理總複雜度是 \(10^7\) 級別的,即暴力列舉每一次加數。
\(x+y+z\) 表示賽時預計 \(x\) 分,實際 \(y\) 分,賽後補了 \(z\) 分。
8.7 模擬賽
4.5 小時 5 道題。
有一道煉石的題,那場我們打過,當時那題場切了。但是現在不會做了【】
有一道 CF 某 div.2 F 的弱化。沒做出來【】
T1. 降溫
賽時想出了做法,拍了一點小資料。但是最後被浮點數的精度和 __int128 掛了。
\(60+100\)。
題意
有 \(n\) 個裝置,每個裝置有初始溫度 \(t_i\)。
給定正整數 \(A, B\),一次降溫操作可以將一個裝置溫度降低 \(A\),剩下 \((n - 1)\) 個裝置溫度降低 \(B\)。
求至少需要多少次降溫操作才能讓所有溫度嚴格小於 \(0\)。
My Solution
我們稱將一個數減少 \(A\) 為特殊操作,減少 \(B\) 為特殊操作。顯然特殊操作的最小次數即答案。
不妨令對 \(i\) 進行了 \(x_i\) 次特殊操作。我們二分它們的和 \(\sum x_i = X\),即答案。
對於 \(i\) 而言,它的特殊操作次數為 \(x_i\),普通操作次數為 \(X - x_i\)。那麼它被減少的量為 \(x_i \cdot A + (X - x_i) \cdot B\)。只有這個值 \(> t_i\) 才能滿足要求。
那麼 check 要做的就是判斷是否存在一個這樣的 \(x\) 陣列,使得每項均為非負整數,且所有數的和為 \(X\),且:
做一些簡單的推導:
不等式上做除法不太好做。考慮分類討論:
若 \(A = B\),那麼在最開始特判即可。答案為 \(\max\{ \lfloor \frac{t_i}A \rfloor +1\}\)。
若 \(A > B\),那麼直接除:
右邊是個常數。我們可以求出在這樣的情況下 \(x_i\) 的最小值。若每個 \(x_i\) 的最小值之和 \(\le X\) 則 check 合法。
若 \(A < B\),除過去要變號:
同理我們可以求出每個 \(x_i\) 的最大值。若每個 \(x_i\) 的最大值之和 \(\ge X\) 則 check 合法。
std Solution
一次降溫操作是選擇一個減 \(A\),剩下全減 \(B\)。那麼我們可以將所有數先全減 \(B\),在選擇某個數加上 \(A - B\)。
仍然二分答案 \(X\)。令 \(a_i = t_i - B \cdot X\)。此時我們需要判斷,能否執行 \(X\) 次操作,每次操作會選擇一個數加上 \(A - B\),使得最終整個序列均為負。
\(A = B\) 太水了。我們考慮:
- \(A > B\):這樣的操作是劣的。因此我們每次找當前的最大值執行這樣的操作。
- \(A < B\):這樣的操作是優的。因此我們每次找當前的最小值執行這樣的操作。
真的操作複雜度不對。
- \(A > B\):維護 \(b_i = \left\{ \begin{matrix} 0 &,a_i \ge 0 \\ \left\lfloor \dfrac{-a_i}{A-B} \right\rfloor + 1&,a_i < 0 \end{matrix}\right.\)。問題等價於 \(\sum b_i \le X\)。
- \(A < B\):同理。不寫了。
程式碼沒寫。
T2. 數學題
\(70+40+100\)。
以為會 70。但是 \((10^4)^2 \times 10 \times 10\) 你覺得能不能過?
題意
求 \(L, R\) 內有多少數的數碼種類為 \(A\)。\(L, R\) 位數都為 \(n \le 2 \times 10^5\)。
做法
差分轉化。考慮 \(1 \sim x\) 的答案。
數位 DP 套路地列舉 \(y \in [1, x]\) 的第一個與 \(x\) 不同的位置 \(i\),並列舉這一位填什麼。這樣我們就得到了 \(y\) 的前 \(i\) 位,且 \(i + 1 \sim n\) 位都可以 \(0 \sim 9\) 任意填。
我們可以求出前 \(i\) 位的種類數 \(B\)。如果 \(B > A\) 那麼不可能。否則如果想讓 \(y\) 的數碼種類為 \(A\),那麼 \(y\) 的 \(i + 1 \sim n\) 位中,一定存在恰好 \((A - B)\) 個與前 \(i\) 位不同的數。這個的方案是 \(\dbinom {10-B}{A-B}\)。
接下來的問題是,在 \((n - i)\) 位中,每個數都有 \(A\) 種填法,但是有 \(B\) 個數至少出現一次。求方案數。
我們容斥列舉,有多少個必選的數沒出現。式子:
複雜度 \(10^2n\)。
T3. 均衡區間
去年做過,而且場切了。現在不會了。
\(30+30+100\)。
題意
給定序列 \(a\),\([l, r]\) 是均衡的當且僅當這個區間的最大值和最小值都不等於 \(a_l\) 和 \(a_r\)。分別求以 \(i\) 為左端點和右端點的均衡區間個數。
\(n \le 10^6\)。
做法
可以輕易求出 \(i\) 左/右邊第一個比自身大/小的位置,單調棧維護。然後我們可以維護 \(f(i)\) 表示當 \(i\) 為右端點時,只要左端點在 \([1, f(i)]\) 內右端點就不是區間最大值或最小值。同理 \(g(i)\) 表示左端點,右端點在 \([g(i), n]\) 就合法。
那麼 \([l, r]\) 合法等價於 \(l \le f(r)\) 且 \(g(l) \le r\)。固定 \(r\)。剩下的是二維數點,即平面上在 \((f(r), r)\) 下面的 \((l, g(l))\) 的數量。
T4. 幾何題
原 CF1991F。
但是仍然不會做。
但是即使會做這題也被卡常樂。
\(45+45+100\)。
題意
維護 \(n\) 根木棍長度。單點修改,求區間內的木棍組成的三角形的最大周長。
做法
首先 CF1991F,我們得知當區間長度 \(\ge 50\) 時一定有解。那麼不妨取出前 \(50\) 大的數。這些數也一定有解,而且最大。
暴力做長度 \(50\) 也是 CF1991F。只需要判斷每相鄰三個即可。
所以我們要做的是求區間前 \(50\) 大。可以線段樹歸併排序,也可以每次取最大值,再把最大值的位置設為 \(-1\)。
T5. 集合題
神秘題。
\(30+30+30\)。
8.8 講課 狀壓 DP、數位 DP
P1896 狀壓 DP。模板題。有一種神秘的輪廓線做法 dan shi wo tai cai le。
CF1209E12 狀壓 DP。很妙的題。兩個巧妙的關鍵點(去最大值限制、將 \(m\) 降到 \(n\))都沒想到。
P9131 狀壓 DP + 高維字首和。想到了一半。
CF55D 數位 DP。用到了一些整除性質。
CF1245F 數位 DP。以前做過。