题目地址
描述
有 n(n≤10000) 种不同的邮票,皮皮想收集所有种类的邮票。唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且买到的邮票究竟是 n 种邮票中的哪一种是等概率的,概率均为 n1。但是由于凡凡也很喜欢邮票,所以皮皮购买第 k 张邮票需要支付 k 元钱。 现在皮皮手中没有邮票,皮皮想知道自己得到所有种类的邮票需要花费的钱数目的期望。
分析
设 gi 为已经拥有了 i 种,买到 n 种的期望次数,那么有:
gi=ni⋅gi+nn−i⋅gi+1化简得到 gi=gi+1+n⋅n−i 且 gn=0。
我们设 fi,j 为已经拥有了 i 种,已经买了 j 张,买到 n 种的期望花费,那么有:
fi,j=ni⋅fi,j+1+nn−i⋅fi+1,j+1+(j+1)这个是没办法算的,因为 j 是可以无限增长的,我们考虑干掉第二维是 j+1 的项,这需要一些恒等式来帮助我们。考虑回到期望最原始的定义上,设 P(i,j) 为已经拥有了 i 种,买 j 次能买到 n 种的概率,则:
gi=k=0∑∞k⋅P(i,k)考虑 fi,j:
考虑 fi,j+1−fi,j:
fi,j+1−fi,j=k=0∑∞k⋅P(i,k)=gi这就说明,fi,j+1=fi,j+gi,我们用这个等式稍微化一下 fi,j 的递推式:
fi,j=ni⋅(fi,j+gi)+nn−i⋅(fi+1,j+gi+1)+(j+1)根据这个递推式,fi,j 只需要 fi+1,j 的值,由于我们只需要知道 f0,0 的答案,我们只对 j=0 做递推,设 Fi=fi,0,那么将上式整理可得:
Fi=n−ii⋅gi+(n−i)(Fi+1+gi+1)+n这就是一个标准的递推式了,复杂度:O(n)。
代码
// Created by Sengxian on 2016/11/28.
// Copyright (c) 2016年 Sengxian. All rights reserved.
// BZOJ 1426 期望 DP
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 10000 + 3;
double f[MAX_N], g[MAX_N];
int main() {
int n;
cin >> n;
g[n] = 0, f[n] = 0;
for (int i = n - 1; i >= 0; --i) {
g[i] = g[i + 1] + (double)n / (n - i);
f[i] = (i * g[i] + (n - i) * (f[i + 1] + g[i + 1]) + n) / (n - i);
}
printf("%.2f\n", f[0]);
return 0;
}