收集邮票C++题目【概率期望DP+数学推导】

题意

Description

n n n 种不同的邮票,皮皮想收集所有种类的邮票。唯一的收集方法是到同学凡凡那里购买,每次只能买一张,并且 买到的邮票究竟是 n n n 种邮票中的哪一种是等概率的,概率均为 1 n \frac{1}{n} n1。但是由于凡凡也很喜欢邮票,所以皮皮购买第k 张邮票需要支付 k k k 元钱。现在皮皮手中没有邮票,皮皮想知道自己得到所有种类的邮票需要花费的钱数目的期望。

Format

Input

一行,一个数字 n n n

Output

要付出多少钱. 保留二位小数

Samples

输入数据 1

3

输出数据 1

21.25

1 ≤ n ≤ 1 0 4 1\leq n\leq 10^4 1n104

思路

这一道题目堪称牛逼,需要数学功底。

P ( x , i ) P(x,i) P(x,i) 表示买 x x x 次能从 i i i 种买到 n n n 种的概率

f i f_i fi 表示现在有 i i i 张,买到 n n n 张的期望。

那么有:
f i = ∑ x = 0 ∞ x × P ( x , i ) ⇔ f i = n − i n × f i + 1 + i n × f i + 1 ⇔ n × f i = ( n − i ) × f i + 1 + i × f i + n ⇔ ( n − i ) × f i = ( n − i ) × f i + 1 + n ⇔ f i = f i + 1 + n n − i . f_i=\sum_{x=0}^\infty x\times P(x,i)\\ \begin{align} &\Leftrightarrow f_i=\frac{n-i}{n}\times f_{i +1} + \frac{i}{n}\times f_i+1\\ &\Leftrightarrow n\times f_i=(n-i)\times f_{i+1}+i\times f_i+n\\ &\Leftrightarrow (n-i)\times f_i=(n-i)\times f_{i+1}+n\\ &\Leftrightarrow f_i=f_{i+1}+\frac{n}{n-i}. \end{align} fi=x=0x×P(x,i)fi=nni×fi+1+ni×fi+1n×fi=(ni)×fi+1+i×fi+n(ni)×fi=(ni)×fi+1+nfi=fi+1+nin.
显然 f n = 0. f_n=0. fn=0.

考虑设 g i , j g_{i,j} gi,j 表示有 i i i 张,下一张是 j j j 的期望。

显然: g i , j → g i , j + 1 g_{i,j}\rightarrow g_{i,j+1} gi,jgi,j+1 的概率为 i n \frac{i}{n} ni g i , j → g i + 1 , j + 1 g_{i,j}\rightarrow g_{i+1,j+1} gi,jgi+1,j+1 的概率为 n − i n \frac{n-i}{n} nni,并且付出代价为 j . j. j.

显然有:
g i , j = i n × g i , j + 1 + n − i n × g i + 1 , j + 1 + j g_{i,j}=\frac{i}{n}\times g_{i,j+1}+\frac{n-i}{n}\times g_{i+1,j+1}+j gi,j=ni×gi,j+1+nni×gi+1,j+1+j
因为这是一个递推式,不妨考虑它的性质:
g i , j = ∑ x = 0 ∞ [ j + ( j + 1 ) + ⋯ + ( x + j − 1 ) ] × P ( x , i ) = ∑ x = 0 ∞ x × ( x + 2 × j − 1 ) 2 × P ( x , i ) \begin{align} g_{i,j}&=&&\sum_{x=0}^\infty\left[j+(j+1)+\dots+(x+j-1) \right]\times P(x,i)\\ &=&&\sum_{x=0}^\infty\frac{x\times(x+2\times j-1)}{2}\times P(x,i)\end{align} gi,j==x=0[j+(j+1)++(x+j1)]×P(x,i)x=02x×(x+2×j1)×P(x,i)
考虑与 g i , j + 1 g_{i,j+1} gi,j+1 发生联系,做差发现:
g i , j + 1 − g i , j = ∑ x = 0 ∞ x × ( x + 2 × j + 1 − x − 2 × j + 1 ) 2 × P ( x , i ) = ∑ x = 0 ∞ x × 2 2 × P ( x , i ) = f i ∴ g i , j = g i , j + 1 − f i . \begin{align}g_{i,j+1}-g_{i,j}=\sum_{x=0}^\infty\frac{x\times(x+2\times j+1 - x-2\times j+1)}{2}\times P(x,i)\\ = \sum_{x=0}^\infty \frac{x\times2}{2}\times P(x,i)= f_i\\ \therefore g_{i,j}=g_{i,j+1}-f_i. \end{align} gi,j+1gi,j=x=02x×(x+2×j+1x2×j+1)×P(x,i)=x=02x×2×P(x,i)=figi,j=gi,j+1fi.
化简该式子:
g i , j = g i , j + 1 × i n + g i + 1 , j + 1 × n − i n + j ⇔ g i , j = ( g i , j + f i ) × i n + ( g i + 1 , j + f i + 1 ) × n − i n + j ⇔ n × g i , j = i × ( g i , j + f i ) + ( g i + 1 , j + f i + 1 ) × ( n − i ) + n × j ⇔ n × g i , j = i × g i , j + i × f i + n × g i + 1 , j − i × g i + 1 , j + n × f i + 1 − i × f i + 1 + n × j ⇔ ( n − i ) × g i , j = ( n − i ) × g i + 1 , j + i × f i + ( n − i ) × f i + 1 + n × j ⇔ g i , j = g i + 1 , j + f i + 1 + i × f i + n × j n − i ⇔ g i , j = g i + 1 , j + f i + 1 + f i × i n − i + n × j n − i g_{i,j}=g_{i,j+1}\times \frac{i}{n}+g_{i+1,j+1}\times\frac{n-i}{n}+j\\ \begin{align} &\Leftrightarrow& g_{i,j}=(g_{i,j}+f_i)\times\frac{i}{n}+(g_{i+1,j}+f_{i+1})\times\frac{n-i}{n}+j\\ &\Leftrightarrow& n\times g_{i,j}=i\times(g_{i,j}+f_i)+(g_{i+1,j}+f_{i+1})\times(n-i)+n\times j\\ &\Leftrightarrow&n\times g_{i,j}=i\times g_{i,j}+i\times f_i+n\times g_{i+1,j}-i\times g_{i+1,j}+n\times f_{i+1}-i\times f_{i+1}+n\times j\\ &\Leftrightarrow& (n-i)\times g_{i,j}=(n-i)\times g_{i+1,j}+i\times f_i+(n-i)\times f_{i+1}+n\times j\\ &\Leftrightarrow& g_{i,j}=g_{i+1,j}+f_{i+1}+\frac{i\times f_i+n\times j}{n-i}\\ &\Leftrightarrow& g_{i,j}=g_{i+1,j}+f_{i+1}+f_i\times\frac{i}{n-i}+\frac{n\times j}{n-i} \end{align} gi,j=gi,j+1×ni+gi+1,j+1×nni+jgi,j=(gi,j+fi)×ni+(gi+1,j+fi+1)×nni+jn×gi,j=i×(gi,j+fi)+(gi+1,j+fi+1)×(ni)+n×jn×gi,j=i×gi,j+i×fi+n×gi+1,ji×gi+1,j+n×fi+1i×fi+1+n×j(ni)×gi,j=(ni)×gi+1,j+i×fi+(ni)×fi+1+n×jgi,j=gi+1,j+fi+1+nii×fi+n×jgi,j=gi+1,j+fi+1+fi×nii+nin×j
显然这里的 j j j 对于转移是无用的,因为我们只需要知道 j = 1 j=1 j=1 的答案,所以说我们的转移如下:
g i = g i + 1 + f i + 1 + f i × i n − i + n n − i g_{i}=g_{i+1}+f_{i+1}+f_i\times\frac{i}{n-i}+\frac{n}{n-i} gi=gi+1+fi+1+fi×nii+nin
于是我们用 O ( n + n ) O(n+n) O(n+n) 解决了这道题目。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iomanip>
#define N 10005
#define ld long double
using namespace std;
int n;
ld f[N],g[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] + f[i] * 1.0 * i / (n - i) + 1.0 * n / (n - i);
	cout << fixed << setprecision(2) << g[0];
	return 0;
}
  • 25
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值