f
[
i
]
f[i]
f[i] 表示当前已经收集了
i
i
i 张邮票的情况下,将
n
n
n 张邮票全部收集的期望费用
f
[
n
]
=
0
f[n]=0
f[n]=0
然后你会发现无法转移——我们不知道现在购买的邮票是第几张
所以再次记录
g
[
i
]
g[i]
g[i] 表示当前已经收集了
i
i
i 张邮票的情况下,将
n
n
n 张邮票全部收集的期望购买次数
显然
g
[
n
]
=
0
g[n]=0
g[n]=0
当
0
≤
i
<
n
0\le i<n
0≤i<n 时,有
g
[
i
]
=
1
+
i
n
g
[
i
]
+
n
−
i
n
g
[
i
+
1
]
g[i]=1+\frac ing[i]+\frac{n-i}ng[i+1]
g[i]=1+nig[i]+nn−ig[i+1]
解方程得
g
[
i
]
=
n
n
−
i
+
g
[
i
+
1
]
g[i]=\frac n{n-i}+g[i+1]
g[i]=n−in+g[i+1]
而
f
[
i
]
f[i]
f[i] 表示当前已经收集了
i
i
i 张邮票,并且下一次购买邮票的费用为
1
1
1 的情况下,将
n
n
n 张邮票全部收集的期望费用
分析下转移:如果当前已经收集了
i
i
i 张邮票,并且现在又用
1
1
1 的费用购买了一张邮票
那么之后所有邮票的费用都加一
而期望情况下之后需要再收集
g
[
i
]
g[i]
g[i] (或
g
[
i
+
1
]
g[i+1]
g[i+1] )张邮票
所以相当于之后多了
g
[
i
]
g[i]
g[i] (或
g
[
i
+
1
]
g[i+1]
g[i+1] )的额外费用
于是
f
[
i
]
=
1
+
i
n
(
f
[
i
]
+
g
[
i
]
)
+
n
−
i
n
(
f
[
i
+
1
]
+
g
[
i
+
1
]
)
f[i]=1+\frac in(f[i]+g[i])+\frac{n-i}n(f[i+1]+g[i+1])
f[i]=1+ni(f[i]+g[i])+nn−i(f[i+1]+g[i+1])
解方程得
f
[
i
]
=
n
n
−
i
+
i
n
−
i
g
[
i
]
+
g
[
i
+
1
]
+
f
[
i
+
1
]
f[i]=\frac n{n-i}+\frac i{n-i}g[i]+g[i+1]+f[i+1]
f[i]=n−in+n−iig[i]+g[i+1]+f[i+1]
最后答案
f
[
0
]
f[0]
f[0]
复杂度
O
(
n
)
O(n)
O(n)
Code
#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define Rof(i, a, b) for (i = a; i >= b; i--)constint N =1e4+5;int n;double f[N], g[N];intmain(){int i;
std::cin >> n;
Rof (i, n -1,0){
g[i]= g[i +1]+1.0* n /(n - i);
f[i]=1.0* n /(n - i)+1.0* i /(n - i)* g[i]+ f[i +1]+ g[i +1];}printf("%.2lf\n", f[0]);return0;}