用 f [ i ] f[i] f[i]表示:现在我手上有 i i i种邮票,期望再买 f [ i ] f[i] f[i]张得到 n n n种邮票。
那么考虑
f
[
i
]
f[i]
f[i]的转移:
当前这一次购买,有
i
n
\frac{i}{n}
ni的概率摸到买过的,有
n
−
i
n
\frac{n-i}{n}
nn−i的概率摸到没买过的。
如果摸到买过的,接下来对应的得到 n n n种邮票的期望就是 i n × f [ i ] \frac{i}{n}\times f[i] ni×f[i]
如果摸到没买过的,现在我手上就有
i
+
1
i+1
i+1种邮票了。
那么接下来对应的得到
n
n
n种邮票的期望就是
n
−
i
n
×
f
[
i
+
1
]
\frac{n-i}{n}\times f[i+1]
nn−i×f[i+1]
于是乎我们得到——
f
[
i
]
=
i
n
×
(
f
[
i
]
+
1
)
+
n
−
i
n
×
(
f
[
i
+
1
]
+
1
)
f[i]=\frac{i}{n}\times(f[i]+1)+\frac{n-i}{n}\times (f[i+1]+1)
f[i]=ni×(f[i]+1)+nn−i×(f[i+1]+1)(这里的
+
1
+1
+1对应这里的一次购买,因为走到这一步也是有消耗的)
当然,上述转移考虑的是每次花费都是
1
1
1。现在题目中要求第
k
k
k次的花费为
k
k
k。
用
g
[
i
]
g[i]
g[i]表示当前有
i
i
i种邮票,买到
n
n
n种邮票还需要的期望花费。
g
[
i
]
=
i
n
×
(
g
[
i
]
+
f
[
i
]
+
1
)
+
n
−
i
n
×
(
g
[
i
+
1
]
+
f
[
i
+
1
]
+
1
)
g[i]=\frac{i}{n}\times(g[i]+f[i]+1)+\frac{n-i}{n}\times(g[i+1]+f[i+1]+1)
g[i]=ni×(g[i]+f[i]+1)+nn−i×(g[i+1]+f[i+1]+1)
这里可以这样理解:我在某个时刻已经买到了 n n n种邮票。考虑最后一次花费为 1 1 1,每往前倒推一次操作,花费就增加 1 1 1。现在时光倒流,我从 i i i种邮票买到 n n n种邮票需要 f [ i ] f[i] f[i]步,那么我从 n n n种邮票退回 i i i种邮票也就会需要 f [ i ] f[i] f[i]步。将步数与花费的关系看作 y = x y=x y=x,那么我如果原来在这次买的是已经有的邮票,我这次的花费就是 f [ i ] + 1 f[i]+1 f[i]+1,因为我后面还要买 f [ i ] f[i] f[i]次。如果买的是没有的邮票,这次的花费就是 f [ i + 1 ] + 1 f[i+1]+1 f[i+1]+1,因为我后面还要买 f [ i + 1 ] f[i+1] f[i+1]次。这里的 f [ i ] + 1 , f [ i + 1 ] + 1 f[i]+1,f[i+1]+1 f[i]+1,f[i+1]+1都是这一步的期望花费。
g [ 0 ] g[0] g[0]就是最后的答案。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;
double f[maxn],g[maxn],n;
int main(){
cin>>n;
for(int i=n-1;i>=0;i--) f[i]=f[i+1]+1.0*n/(n-i);
for(int i=n-1;i>=0;i--) g[i]=g[i+1]+f[i+1]+1.0*f[i]*i/(n-i)+1.0*n/(n-i);
printf("%.2lf",g[0]);
}