題目的難度顏色使用 Luogu 上的分級,由簡單到困難分別為 🔴🟠🟡🟢🔵🟣⚫。
Problem Statement
題目簡述
有 n 顆星排列在 [1,n]。Iris 觀察星星的遞迴過程如下:
對於當前區間 [l,r],計算中間位置 m=⌊2l+r⌋。
- 若區間長度 len=r−l+1 為偶數,則將其分為 [l,m] 和 [m+1,r] 兩個子區間繼續觀察。
- 若區間長度 len 為奇數,則將 m 加入幸運值,並將其分為 [l,m−1] 和 [m+1,r] 兩個子區間繼續觀察。
- 若區間長度小於 k,則停止觀察。
求最終的幸運值總和。
Constraints
約束條件
- 1≤k≤n≤2⋅109
思路:遞迴與對稱性 (Recursion & Symmetry)
由於 n 可達 2⋅109,我們不能直接模擬整個過程,必須尋找規律。
觀察:中心對稱性
關鍵觀察
觀察遞迴的分裂過程:
- 每次分裂時,區間被分為左右兩半(若為奇數長度則去掉中間點)。
- 對於原始區間 [1,n],左半部分和右半部分的處理過程完全對稱。
- 任何被選中的位置 m,在對稱的另一側必有一個對應位置被選中。
這個對稱中心為 2n+1。
由此可得:
核心性質
被選中的所有星星下標關於 2n+1 對稱。
若選中的星星總數為 cnt,則它們的總和為:
Ans=cnt×2n+1
計算選中數量 cnt
定義遞迴函數 dfs(len) 計算長度為 len 的區間會選中多少顆星:
- 終止條件:若
len < k,不再分裂,回傳 0。
- 遞迴步驟:
- 若
len 為偶數:分為兩段長度 ⌊2len⌋ 的區間,不選中任何星。
- 若
len 為奇數:中間點被選中 (+1),再分為兩段長度 ⌊2len⌋ 的區間。
綜合起來,遞迴式為:
dfs(len)=⎩⎪⎪⎨⎪⎪⎧02⋅dfs(⌊2len⌋)+(lenmod2)if len<kif len≥k
最終答案即為 dfs(n)×2n+1。
整數性保證
- 當 n 為偶數時:選中的總數 cnt 必為偶數(因偶數長度區間本身不選中任何點),因此 cnt×(n+1) 必能被 2 整除。
- 當 n 為奇數時:(n+1) 為偶數,因此 cnt×(n+1) 必能被 2 整除。
綜上,無論 n 奇偶,計算結果皆為整數。
複雜度分析
- 時間複雜度:O(logn),每次遞迴長度減半,深度為 logn。
- 空間複雜度:O(logn),遞迴堆疊深度。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13
| def solve(): n, k = map(int, input().split())
def dfs(ln): if ln < k: return 0 return 2 * dfs(ln // 2) + (ln & 1) print(dfs(n) * (n + 1) // 2)
if __name__ == "__main__": t = int(input()) for _ in range(t): solve()
|
寫在最後
PROMPT