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);
}
posted @ 2020-11-06 09:40  Anverking  阅读(298)  评论(0编辑  收藏  举报