LG 題解 CF710E Generate a String
阿新 • • 發佈:2021-12-22
這好像是出給學弟的模擬賽題
Solution
顯然需要考慮 DP。觀察資料範圍設 \(f_i\) 表示生成一個長度為 \(i\) 的字串所需要的最少花費。
三個操作對應著 \(i \to i - 1, i \to i + 1, i \to i \times 2\)。
如果沒有中間那個操作,顯然每個狀態只會由前面的狀態轉移而來,直接轉移即可,轉移方程如下:
\[f_i = \min \{ f_{i-1} + X \} \]\[f_i = \min \{ f_{i/2} + Y\} (i \bmod 2 =0) \]考慮中間的操作 \(i \to i + 1\),它需要使用到後面的狀態,這個狀態我們現在並沒有更新。那麼我們想:我們能不能從 \(\frac{i+1}{2} \to i+1 \to i\)
想了想是可以的。並且只需要在 \(i \bmod 2 = 1\) 的時候考慮這個轉移即可,所以有轉移方程:
\[f_{i} = \min \{ f_{(i+1)/2} + X + Y \}(i \bmod 2 = 1) \](如果 \(i \bmod 2 = 0\) 的話根本不需要 \(-1\))
把這三個轉移方程結合起來這題就做完了,時間複雜度 \(\mathcal O(n)\)。
Code
#include<bits/stdc++.h> #define int long long using namespace std; const int MAXN = 1e7 + 10; int n, X, Y; int f[MAXN]; signed main() { cin >> n >> X >> Y; memset(f, 0x3f, sizeof f); f[0] = 0; for(int i = 1; i <= n; ++i) { f[i] = min(f[i], f[i - 1] + X); if(i & 1) { f[i] = min(f[i], f[i + 1 >> 1] + X + Y); } else { f[i] = min(f[i], f[i >> 1] + Y); } } printf("%lld\n", f[n]); return 0; }