Codeforces 🎨 CF2179D. Blackslex and Penguin Civilization
🔗 CF2179D Blackslex and Penguin Civilization
rating: 1343
Problem Statement
題目簡述
給定 ,求一個 到 的排列 ,首先使得 最大,其次要求該排列的字典序最小。
Constraints
約束條件
思路:貪心構造
這道題有兩個目標:
-
最大化 :
是 的二進位表示中 的個數。 是所有前綴 AND 值的 popcount 總和。
前綴 AND 的值只會隨著序列長度增加而減少(或不變)。要最大化總和,我們希望前綴 AND 的每一位 能維持越久越好。
對於 個位元中的任意一位 ,在排列中最多只有 個數的第 位是 。因此,第 位為 的前綴長度上限是 。
顯然,我們可以構造出一種排列,使得不同位元的「生存時間」分別為 。其總和是固定的。 -
字典序最小:
為了讓排列的字典序最小,我們希望數值越小的元素越早出現。
數值小意味著高位元是 。
因此,我們應該儘早放棄高位元的限制(讓高位元在前綴 AND 中變為 0),並盡可能保留低位元為 。
這意味著我們應該優先輸出低位元全為 的數。
具體構造策略
我們可以根據數字二進位表示中尾部連續 的數量(Trailing Ones)將所有數字分組,依序處理 :
- 具 個連續 1 ():即 。這是唯一的,必須放在最前面。
- 具 個連續 1 ():這些數字需滿足:
- 低 位元全為 1:確保加入這些數後,前綴 AND 最少還有 個 1。
- 第 位元為 0:區分屬於更低階的群組(否則若第 位為 1,則應屬於 群組)。
對於每個 (從 遞減至 ),該分組中最小的數為 (低 位為 1,第 位為 0,高位全 0)。
後續符合條件的數字可以通過不斷加上 (即跳過第 位,只動高位)來生成。
這形成了一個首項為 、公差為 、且末項 的等差數列:range((1 << k) - 1, (1 << n) - 1, (1 << (k + 1)))。
此順序自然滿足字典序最小的要求。
範例
- 先加入。
- : 起始
0111(), 公差10000()。- 。
- : 起始
0011(), 公差1000()。- 。
- : 起始
0001(), 公差0100()。- 。
- : 起始
0000(), 公差0010()。- 。
注意:初始時會先將 加入答案。
最終排列:15, 7, 3, 11, 1, 5, 9, 13, 0, 2, 4, 6, 8, 10, 12, 14。
複雜度分析
- 時間複雜度:,每個數字只被訪問並輸出一次。
- 空間複雜度: 用於存儲排列。
Code
1 | def solve(): |
寫在最後
PROMPT
這裡什麼都沒有。
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 十六個天亮!
評論
WalineGiscus







