Codeforces 🟢 CF2173D. Taiga's Carry Chains
題目的難度顏色使用 Luogu 上的分級,由簡單到困難分別為 🔴🟠🟡🟢🔵🟣⚫。
CF2173D Taiga’s Carry Chains
Problem Statement
題目簡述
給定一個正整數 和操作次數 。
每次操作你可以選擇一個非負整數 ,並執行 。
定義單次操作的分數為加法過程中產生的二進位進位次數。
求 次操作後的最大總分數。
Constraints
約束條件
思路
1. 轉化問題目標
首先觀察二進位加法中進位次數與 Popcount(二進位中 1 的個數)的關係。
令 為 的二進位中 1 的個數。對於加法 ,設進位次數為 ,則滿足:
移項可得單次操作的進位數:
將 次操作的總分累加:
因此,要最大化總分,等價於最小化最終數值 的二進位 1 的個數 。
2. 貪婪策略與特殊情況
我們的目標是構造一個增量 ,使得 最小。
由於 ,二進位長度約為 30。
- 當 足夠大時 ():
我們擁有足夠的「預算」來填補 二進位中的空隙並引發連鎖進位,最終可以將 變成一個 的冪次(即 )。
此時最大得分為 。為什麼是 32?因為 最多 30 位,只要能湊出足夠的進位,就能不斷合併低位的 1,直到只剩下一個最高位的 1。32 次操作綽綽有餘。
3. 數位 DP (Digit DP)
當 較小時,我們無法保證能將結果變成 的冪次,此時使用數位 DP 來尋找最優解。
我們從低位到高位處理,決定每一位是否要分配一個 的加法操作。
狀態定義:dfs(i, j, carry)
- :當前處理的位元位置(從 0 開始)。
- :剩餘可用的操作次數(預算)。
- :來自低位的進位值。
轉移方程:
對於第 位,設 的第 位為 。我們有兩種選擇:
- 不在此位加 :消耗 0 次操作。
- 當前位總和
tot = b + carry
- 當前位總和
- 在此位加 :消耗 1 次操作(需 )。
- 當前位總和
tot = b + carry + 1
- 當前位總和
計算該位留下的 bit (tot & 1) 與產生的新進位 (tot >> 1),取兩者中能使後續 Popcount 最小的方案。
邊界條件 (Base Case):
當 的位元都處理完且沒有進位時 ((n >> i) == 0 and carry == 0):
此時若還有剩餘預算 ,相當於我們還需要在更高的位元加上 個 的冪次。
由於我們已經超過了 的最高位,能得到的最小 Popcount 發生在加上 個 時。
這個數值的 Popcount 即為 j.bit_count()。
複雜度分析
- 時間複雜度:。
- 狀態數量為 ,每個狀態需要 的時間來計算。
- 由於 DP 中 被限制在 32 以內,且位數約為 30,每個 Testcase 幾乎是常數時間。
- 空間複雜度:。
Code
1 | from functools import cache |
寫在最後
PROMPT
這裡什麼都沒有。
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 十六個天亮!
評論
WalineGiscus







