bzoj2720 [Violet 5]列队春游 (期望概率)

53 篇文章 0 订阅
51 篇文章 1 订阅

bzoj2720 [Violet 5]列队春游 (期望概率)

原题地址http://www.lydsy.com/JudgeOnline/problem.php?id=2720

题意:
这里写图片描述
这里写图片描述
这里写图片描述
数据范围
保证 1≤n≤300,1≤hi≤1000
题解:
这题理解了好久,O(n^3)和O(n^2)好麻烦
以下是O(n)的做法:
对于一个高度为h的学生i,比他高度小的有s个,高度为h的有num[h]个。
我们需要计算对于这个高i的学生,他的期望视野是多少。
可以看到,一个学生的视野就是 前面比他矮的个数+1
我们暂且不看那个+1,先来算前面期望比他矮的个数
若有学生j∈s集合,即j比i矮,设f[i]为前面期望比i矮的个数,d[j]是j对i的贡献,p[j]是j对i有贡献的概率。
p[j]=(j对i有贡献的排列数)/(n个学生的总排列数)

d[j]=1*p[j]
那么
f[i]=sum((j∈s)d[j])
那么p[j]怎么算呢?
要满足j对i有贡献,那么j与i之间只能有其他属于s集合的学生,有s-1个。
先忽略这s-1个学生,现在还剩n-s+1个学生。那么这些学生的排列中,j刚好在i前一个的排列有: (n-s)! 个
而剩下(s-1)个比i矮的学生的分散在上述排列中的排列有
(n-s)!* A(n,s-1)
=( (n-s)!* n! ) / (n-s+1)!
=n!/(n-s+1)
只有在这些排列中,i与j之间都不会出现比i高或和i一样高的,即j对i有贡献。
p[j]
=(n!/(n-s+1))/ n!
=1/( n-s+1)
f[i]=s*1/( n-s+1)= s/( n-s+1)
别忘了视野=f[i]+1
因为高度为h的有num个
所以对这num[h]个人的期望=num[h]*( (s/( n-s+1)) +1 ) )
=num[h]*s/(n-s+1) + num[h]
所以
ans=sum((i∈[1,1000]) num[i]*s/(n-s+1) + num[i])
处理完后,s每次加上当前的num[i]就行
//赞叹一发自己的机智

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1005;
int n,num[N],h,s=0;
double ans=0.0;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&h);
        num[h]++;
    }
    for(int i=1;i<=1000;i++)
    {
        if(num[i])
        ans+=(double)(num[i]*s)/(n-s+1)+double(num[i]);
        s+=num[i];
    }
    printf("%0.2lf\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值