百度松果 小码哥考研小技巧 (概率期望)

本文介绍了一种通过优化单词背诵顺序来最大化背诵效率的方法。通过对单词按特定条件排序,实现背诵长度期望值的最大化。

题目描述

要考研了,小码哥非常焦急,他要开始背英语单词,每个单词的长度是lil_ili ,小码哥有pipipi的概率认识这个单词,小码哥要从一个有nnn个单词的总清单里按顺序的背单词,小码哥有一个认识清单,里面放的都是他认识的单词,如果小码哥背到第iii个单词不认识这个单词,小码哥会把该单词背一遍并且把自己认识的单词从头背一遍,如果小码哥认识这个单词,他会把该单词背一遍,并且把这个单词放进自己的认识清单里。问如何排序小码哥背单词的长度的期望最大,期望是多少。

输入格式

第一行包含单个整数n(1≤n≤50000)n(1\le n\le 50000)n(1n50000)。下面nnn行中的第iii行包含两个整数,用一个空格隔开lil_ilipip_ipi(1≤li≤1000,0≤pi≤1001\le l_i\le 1000,0\le pi\le 1001li1000,0pi100)——第iii个单词的长度和小码哥认识这个单词的概率(以百分比为单位)。

输出格式

单行打印单个实数表示小码哥背单词的长度的最大期望。绝对误差或相对误差不超过10−910^{-9}109

输入样例1
3
100 6
100 8
100 10
输出样例1
326.12
输入样例2
5
100 6
100 8
100 10
2 99
1000 1
输出样例2
1364.045

分析

我们要为所有的单词排一个顺序,使得最终背诵的单词长度期望最大。
wiw_iwi为单词iii的权值 li∗pil_i*p_ilipi
假设a、b两个单词,如果小码哥先背b后背a,那么他背到a的时候期望要加上

la∗pa+(1−pa)∗(w其他+wb+wa)(1)l_a*p_a+(1-p_a)*(w_{其他}+w_b+w_a)\qquad (1)lapa+(1pa)(w其他+wb+wa)(1)
如果先背a后背b那么背到b时他的期望要加上:
lb∗pb+(1−pb)∗(w其他+wb+wa)(2)l_b*p_b+(1-p_b)*(w_{其他}+w_b+w_a)\qquad (2)lbpb+(1pb)(w其他+wb+wa)(2)
我们给(1)式子乘上(1−pb)(1-p_b)(1pb),(2)式乘上(1−pa)(1-p_a)(1pa)
la∗pa∗(1−pb)+(1−pa)∗(1−pb)∗(w其他+wb+wa)(1)l_a*p_a*(1-p_b)+(1-p_a)*(1-p_b)*(w_{其他}+w_b+w_a)\qquad (1)lapa(1pb)+(1pa)(1pb)(w其他+wb+wa)(1)
lb∗pb∗(1−pa)+(1−pb)∗(1−pa)∗(w其他+wb+wa)(2)l_b*p_b*(1-p_a)+(1-p_b)*(1-p_a)*(w_{其他}+w_b+w_a)\qquad (2)lbpb(1pa)+(1pb)(1pa)(w其他+wb+wa)(2)
之后我们会发现一个公共项可以约掉:
(1−pa)∗(1−pb)∗(w其他+wa+wb)(1-p_a)*(1-p_b)*(w_{其他}+w_a+w_b)(1pa)(1pb)(w其他+wa+wb)
如果(1)−(2)>0(1)-(2)>0(1)(2)>0
la∗pa∗(1−pb)−lb∗pb∗(1−pa)>0(3)l_a*p_a*(1-p_b)-l_b*p_b*(1-p_a)>0\qquad (3)lapa(1pb)lbpb(1pa)>0(3)

所以我们要取到最优解,就要满足(3)(3)(3)式的排序方法。
排序后将所有的概率和权值相乘后累加即可。

C++ 代码
#include<bits/stdc++.h> 
using namespace std;
const double eps=1e-9;
//定义一个结构体
struct node{
    int len,theta;
    
    bool operator<(const node &p) const{
        if(len*theta*(1-1.0*p.theta/100)-p.len*p.theta*(1-1.0*theta/100))
        {
        	//满足关系(3)进行排序
            if(len*theta*(1-1.0*p.theta/100)>p.len*p.theta*(1-1.0*theta/100)){
                return 1;
            }
        }
        return 0;
    };  
};
int n,,l,r;
long double ans,Summul;
int main()
{
    vector<node> v,maxn;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>l>>r;
        v.push_back({l,r});
    }
    sort(v.begin(),v.end());
    
    for(int i=0;i<n;i++)
    {
    	//加上这个单词的期望
        ans+=(long double)v[i].len*v[i].theta*1.0/100+(long double)(Summul+v[i].len)*(1-v[i].theta*1.0/100);
        //更新 w其他
        Summul+=(long double)v[i].len*v[i].theta*1.0/100;
    }
	
	//将答案转换为字符串形式
    string s=to_string(ans);
    //将小数点后的多余的'0'给去掉
    while(s.back()=='0') s.pop_back();
    cout<<s;
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jay_fearless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值