我是看不懂啊 直接粘dalao的 鏈結
設g[i]表示已經收集了i張郵票,要收集到n張郵票的期望購買次數。
設pr(x, i)表示已經收集了i張郵票,購買x次能收集到n張郵票的概率。
那麼根據g[i]定義,有
(pr(x, i)是可以表示出來的,但是表示出來也沒有實際用處,所以為了方便,設為pr(x, i))
但是我們計算g[i]並不能用定義式,因為是無窮的,而且過於麻煩。
其實g[i]的問題是一類經典問題,這類問題的解決方法是遞推。
由結論,有
這裡證明一下為什麼是加n / (n - i)…
假設現在有i張郵票,那麼可以通過
(1)抽一次得到i + 1張郵票,期望為1 * (n - i) / n
(2)抽兩次得到i + 1張郵票,期望為2 * i / n * (n - i) / n
(3)抽三次得到i + 1張郵票,期望為3 * (i / n)^2 * (n - i) / n
(4)…
顯然是乙個無窮級數,相當於求
這個式子用錯位相減法搞一搞,求出來就是n / (n - i),高中數學內容就不詳細說了…
那麼現在可以求出g[i]了,先把這個陣列放一邊,一會用。
設f[i][j]表示已經收集了i張郵票,買下一張郵票需要花費j元,收集到n張的期望花費。
那麼有兩種情況
(1)沒收集到i + 1張郵票,期望為f[i][j + 1] * i / n
(2)收集到了i + 1張郵票,期望為f[i + 1][j + 1] * (n - i) / n
花費都為j,得到
但是這還是個無窮的表示式(j會非常大),並不能直接拿去用。
利用f[i][j]的定義,再列出乙個定義式。
(這個定義式有點神奇…)
根據這個整理後的定義式,列出f[i][j + 1],並作差,可以得到
發現這玩意」恰好」就是g[i]。
我們把f[i][j + 1]代入到上面推出的遞推式裡,整理一下。
變成了乙個方程,把f[i][j]表示出來。
然後就可以遞推了?等會,注意到f[i][j]裡還有個j,我們該開多大陣列?然後再看看,發現除過j,沒有用到其他的值(比如j+1, j+2, j-1啥的),整個式子裡只有j這一維。
顯然我們要求的是f[0][1],所以我們把j都變成1就好了,這樣就不用第二維了。
完啦。答案為f[0]。
#include
typedef
double db;
const
int maxn = 10005;
int n;
db g[maxn], f[maxn];
int main()
BZOJ 1426 收集郵票 概率DP
f i 表示現在有 i 張,買到 n 張的期望 所以 f i f i 1 frac 費用提前計算,每張郵票看做一元,然後使後面每一張加1元 g i 表示當前為 i 張期望到 n 張時花掉的錢。那麼 g i g i 1 f i 1 fracf i frac 遞推即可 include include i...
bzoj 1426 收集郵票(概率期望dp)
time limit 1 sec memory limit 162 mb submit 551 solved 460 submit status discuss 有n n 種不同的郵票,皮皮想收集所有種類的郵票。唯一的收集方法是到同學凡凡那裡購買,每次只能買一張,並且 買到的郵票究竟是 n role...
BZOJ 1426 收集郵票 期望DP
有n種不同的郵票,皮皮想收集所有種類的郵票。唯一的收集方法是到同學凡凡那裡購買,每次只能買一張,並且買到的郵票究竟是n種郵票中的哪一種是等概率的,概率均為1 n。但是由於凡凡也很喜歡郵票,所以皮皮購買第k張郵票需要支付k元錢。現在皮皮手中沒有郵票,皮皮想知道自己得到所有種類的郵票需要花費的錢數目的期...