题解 CF235B 【Let's Play Osu!】

题目描述

定义一个\(01\)序列的价值为其所有极长连续\(0\)子段长度的平方和。

举例来说,\(0010001100\)的价值为\(2^2+3^2+2^2=17\)

现有一序列,你只知道第\(𝑖\)个位置是\(0\)的概率为\(𝑝_𝑖\),为\(1\)的概率为\(1−𝑝_𝑖\),你需要计算其价值的期望。

输入格式

第一行包含\(1\)个正整数\(𝑛\)表示序列长度。

第二行\(𝑛\)个实数表示\(𝑝_𝑖\)

输出格式

输出一行一个实数表示答案,保留三位小数。

解题思路

一直对期望这东西不太透彻,别人觉得很显然的东西但我觉得一点也不显然(,所以只会尝试从期望的定义硬推柿子。我们定义对于集合\(S\)\(r_i\)表示对于目前序列连续\(0\)字段的长度

根据题意,我们设\(ans_i=\sum_{k\in S}p_k\times (r_{1}^2+r_{2}^2+r_{3}^2+....+r_{ki}^2)\)\(f_i=\sum_{k\in S}p_k\times r_{ki}\),其中\(ans\)为答案,\(f_i\)表示到第\(i\)格的期望连击数

考虑如何转移,设第\(i\)格为\(0\)的概率为\(a_i\),对于\(f_i\),我们有\(f_{i+1}=\sum_{k\in s}a_{i+1}\times p_k\times (r_k+1)+ \sum_{k\in s}(1-a_{i+1})\times p_k \times 0\)

考虑这个柿子是什么意思,对于你目前的格子你只会有两种状态\(0\)\(1\),这个柿子的前面对应着此格子为\(0\)的期望,后面为此格子若为\(1\)的期望,因为\(1\)的贡献为\(0\)所以我们直接舍去

那么到最后\(f_{i+1}=\sum_{k\in s}a_{i+1}\times p_k\times (r_k+1)\)

然后对这个柿子进行一下简单的移项操作可以得到

\(f_{i+1}=\sum_{k\in s}a_{i+1}\times p_k\times (r_k+1)=a_{i+1}(\sum_{k\in s}p_k\times r_k+\sum_{k\in s}p_k)=a_{i+1}\times (f_i+1)\)

考虑\(ans\)如何转移,对于\(ans_{i+1}=\sum_{k\in s}a_{i+1}\times p_k\times (r_{1}^2+r_{2}^2+....+(r_{ki}+1)^2)+\sum_{k\in s}(1-a_{i+1})\times p_k\times (r_{1}^2+r_{2}^2+....+r_{ki}^2)\)

然后剩下的就是合并同类项之类的操作了qwq,最后得到\(ans_{i+1}=ans_i+(2\times f_i+1)\times p_{i+1}\)(这东西貌似根据期望的线性性很显然,但是我不太明白)

Code

#include<bits/stdc++.h>
    
#define LL long long
    
#define _ 0
    
#define AME__DEBUG
    
using namespace std;
    
/*Grievous Lady*/
    
const int BUF_SIZE = 1 << 12;
    
char buf[BUF_SIZE] , *buf_s = buf , *buf_t = buf + 1;
    
#define PTR_NEXT() \
{ \
    buf_s ++; \
    if(buf_s == buf_t) \
    { \
        buf_s = buf; \
        buf_t = buf + fread(buf , 1 , BUF_SIZE , stdin); \
    } \
}
    
template <typename _n_> void mian(_n_ & _x_){
    while(*buf_s != '-' && !isdigit(*buf_s)) PTR_NEXT();
    bool register _nega_ = false; if(*buf_s == '-'){ _nega_ = true; PTR_NEXT(); }
    _x_ = 0; while(isdigit(*buf_s)){ _x_ = _x_ * 10 + *buf_s - '0'; PTR_NEXT(); } if(_nega_) _x_ = -_x_;
}
    
template <typename _n_> bool cmax(_n_ &a , const _n_ &b){ return a < b ? a = b , 1 : 0; }
    
template <typename _n_> bool cmin(_n_ &a , const _n_ &b){ return a > b ? a = b , 1 : 0; }

#define qwq double

const int kato = 1e5 + 10;

int n;

qwq yuni , a[kato] , osu[kato];

inline int Ame_(){
#ifdef AME__
    freopen(".in" , "r" , stdin); freopen(".out" , "w" , stdout);
#endif
    mian(n);
    for(int i = 1;i <= n;i ++){
        scanf("%lf" , &yuni);
        a[i] = (a[i - 1] + 1) * yuni;
        osu[i] = osu[i - 1] + (2 * a[i - 1] + 1) * yuni;
    }
    printf("%.3lf\n" , osu[n]);
    return ~~(0^_^0);
}
    
int Ame__ = Ame_();
    
int main(){;}
posted @ 2020-10-07 06:28  Ame_sora  阅读(178)  评论(0编辑  收藏  举报