JZOJ 3885. 【长郡NOIP2014模拟10.22】搞笑的代码

Description

在OI界存在着一位传奇选手——QQ,他总是以风格迥异的搞笑代码受世人围观
某次某道题目的输入是一个排列,他使用了以下伪代码来生成数据
while 序列长度< n do
{
随机生成一个整数属亍[1,n]
如果这个数没有出现过则加入序列尾
}
聪明的同学一定发现了,这样生成数据是徆慢的,那么请你告诉QQ,生成一个n排列的期望随机次数

Input

一个正整数n,表示需要生成一个n排列

Output

一个数表示期望随机次数,保留整数

Sample Input

4

Sample Output

8(.333333…)

【友情提示】

输出样例的括号里表示答案的小数部分,但实际丌要求输出
数学期望=sigma(概率* 权值),本题中为期望随机次数=sigma(概率*随机次数)

Data Constraint

30%数据满足 n3
80%数据满足 n107
100%数据满足 n231

Solution

  • 这题是经典的概率期望题。

  • 定义 fi 表示 序列长度为 i 时的期望随机次数,不难根据题目的定义列出递推式:

    fi=in(fi+1)+nin(fi1+1)

  • 解得:

    fi=fi1+nni

  • 所以答案就是:

    i=1nni

  • 但然而数据范围很大,单纯的 O(N) 处理是会超时的。

  • 于是两个“高深”的算法便横空出世了!

      • 打表!!!——每隔 107 打一个数,暴力处理!~
      • 运用 欧拉常数调和级数 处理,在 N 很大时误差极小;

      • 之后在 N107 时同样暴力处理即可。

      • 具体公式为:

        Ans=logeNEulerN

Code

#include<cstdio>
#include<cmath>
using namespace std;
const double Euler=0.57721566490153286060651209;
int n;
double ans;
int main()
{
    scanf("%d",&n);
    if(n>1e7) ans=log(n)+Euler; else
        for(int i=1;i<=n;i++) ans+=1.0/i;
    printf("%.0lf",n*ans);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值