方伯伯有一天去參加乙個商場舉辦的遊戲。商場派了一些工作人員排成一行。每個人面前有幾堆石子。說來也巧,位置在 \(i\) 的人面前的第 \(j\) 堆的石子的數量,剛好是 \(i\) 寫成 \(k\) 進製後的第 \(j\) 位。
現在方伯伯要玩乙個遊戲,商場會給方伯伯兩個整數 \(l,r\)。方伯伯要把位置在 \([l,r]\) 中的每個人的石子都合併成一堆石子。每次操作,他可以選擇乙個人面前的兩堆石子,將其中的一堆中的某些石子移動到另一堆,代價是移動的石子數量 \(\times\) 移動的距離。商場承諾,方伯伯只要完成任務,就給他一些椰子,代價越小,給他的椰子越多。所以方伯伯很著急,想請你告訴他最少的代價是多少。
輸入僅有一行,包含三個用空格分隔的整數 \(l\),\(r\),\(k\),表示商場給方伯伯的兩個整數,以及進製數。
輸出僅有一行,包含乙個整數,表示最少的代價。
考慮用 \(1\sim r\) 的答案減掉 \(1\sim l-1\) 的答案,即 \(\operatorname(r) - \operatorname(l-1)\)。
考慮 \(\operatorname(n)\),先計算把每個人的石子都全部合併到第 \(1\) 堆所需的代價
這個是可以通過一次數字dp解決的
注意到這樣乙個性質:對於乙個人 \(x\),假設他把所有石子最終全部移到第 \(k\) 位,我們把 \(k\) 叫做 \(x\) 的集合點,這樣移動的代價是 \(f_x(k)\),那麼 \(f_x\) 一定是乙個單谷函式ll dfs1(ll d, ll sum, ll lim)
if (!lim) f[d][sum] = ret;
return ret;
}
不妨把 \(x\) 的最優集合點叫做 \(p_x\)
所以我們可以執行這樣的操作:
for i=2~n
,每次把所有 "集合點在 \(i\) 時比在 \(i-1\) 時更優 (即 \(f_x(i-1)>f_x(i)\))" 的那些 \(x\) 的集合點全部從 \(i-1\) 變為 \(i\),也就是說讓答案減去 \(f_x(i-1)-f_x(i)\)
這樣一來,由於 \(f_x\) 是單谷函式,那麼乙個人 \(x\) 一定在 \(i=2\sim p_x\) 的時候集合點被移動,那麼 \(x\) 的最終代價就會是 \(f_x(p_x)\),所以這個做法是正確的
然後考慮如何進行這個"挪動集合點"的操作 其實和上面的那個計算集合點全為1的數字dp區別不大
ll dfs2(ll d, ll sum, ll p, ll lim)
if (!lim) f[d][sum] = ret;
return ret;
}
#include using namespace std;
typedef long long ll;
ll k, len, a[60];
ll l, r, f[60][5005];
ll dfs1(ll d, ll sum, ll lim)
if (!lim) f[d][sum] = ret;
return ret;
}ll dfs2(ll d, ll sum, ll p, ll lim)
if (!lim) f[d][sum] = ret;
return ret;
}ll solve(ll n)
memset(f, -1, sizeof(f));
ll ret = dfs1(len, 0, 1);
for (ll i = 2; i <= len; i++)
return ret;
}int main()
SCOI2014 方伯伯的商場之旅
方伯伯有一天去參加乙個商場舉辦的遊戲。商場派了一些工作人員排成一行。每個人面前有幾堆石子。說來也巧,位置在 i 的人面前的第 j 堆的石子的數量,剛好是 i 寫成 k 進製後的第 j 位。現在方伯伯要玩乙個遊戲,商場會給方伯伯兩個整數 l,r。方伯伯要把位置在 l,r 中的每個人的石子都合併成一堆石...
SCOI2014 方伯伯的商場之旅
題目描述 方伯伯有一天去參加乙個商場舉辦的遊戲。商場派了一些工作人員排成一行。每個人面前有幾堆石子。說來也巧,位置在 i 的人面前的第 j 堆的石子的數量,剛好是 i 寫成 k 進製後的第 j 位。現在方伯伯要玩乙個遊戲,商場會給方伯伯兩個整數 l,r 方伯伯要把位置在 l,r 中的每個人的石子都合...
方伯伯的商場之旅(數字DP)
description 方伯伯有一天去參加乙個商場舉辦的遊戲。商場派了一些工作人員排成一行。每個人面前有幾堆石子。說來也巧,位置在 i 的人面前的第j 堆的石子的數量,剛好是 i 寫成 k 進製後的第 j 位。現在方伯伯要玩乙個遊戲,商場會給方伯伯兩個整數l,r。方伯伯要把位置在 l,r 中的每個人...