LG P5147 随机数生成器
题目描述
HKE最近编写了一个函数 \(\text{rand}(l,r)\),其中 \(l,r\) 为正整数且 \(l \le r\)。这个函数会等概率返回区间 \([l,r]\) 中任意一个正整数。然后,他又编写了一个函数:
int work(int x){
if(x==1) return 0;
else return work(rand(1,x))+1;
}
现在给定一个正整数 \(n\),请问 \(\text{work}(n)\) 的返回值的期望值是多少?对于\(70\%\)的数据,\(n\le 10^6\),对于\(100\%\)的数据,\(n<2^{31}\)。
分析
设\(f_i\)为\(\text{work}(i)\)的期望,那么
\[f_i=\dfrac1{i}\sum_{j=1}^i f_j+1
\]
边界\(f_1=0\)。记\(S_i\)为\(f_i\)的前\(i\)项和,则
\[f_i=\dfrac1iS_i+1
\]
同理有\(f_{i-1}=\dfrac1iS_{i-1}+1\)。将两式相减得
\[if_i-(i-1)f_{i-1}=S_i-S_{i-1}+1
\]
整理即得
\[f_i=f_{i-1}+\dfrac1{i-1}
\]
从而
\[f_i=\sum_{j=1}^{i-1}+1=H_{i-1}+1
\]
其中\(H_{i-1}\)为第\(i-1\)项调和数。
对于\(70\%\)的数据,可以\(O(n)\)递推\(f_n\)。注意到当\(n\)充分大时,有\(H_n\approx \ln n+\gamma\),其中\(\gamma\approx 0.57721566490153286\)为欧拉常数,\(O(1)\)即可计算。
Code
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
const double g=0.57721566490153286;
double sum;
int n;
int main()
{
scanf("%d",&n);
if(n<=1e6)
for(int i=1;i<=n-1;++i)
sum+=1.0/i;
else
sum=log(n)+g;
printf("%.5lf\n",n==1?0:sum+1.0);
}
The man who follow the shadow is just the shadow itself.