牛客OI周赛D-Talk(期望dp)

    科技2024-11-19  23

    很容易想到定义 d p [ i ] dp[i] dp[i]是已经执行了前 i i i个事件,还期望讲多久结束

    d p [ i ] = p [ i ] ∗ ( d p [ i + 1 ] + 1 ) + ( 1 − p [ i ] ) ∗ ( d p [ i − 1 ] + 1 ) dp[i]=p[i]*(dp[i+1]+1)+(1-p[i])*(dp[i-1]+1) dp[i]=p[i](dp[i+1]+1)+(1p[i])(dp[i1]+1)

    发现这个式子前后都有依赖,可以高斯消元,但这题似乎卡这个精度

    我 们 这 么 定 义 d p [ i ] \color{Red}我们这么定义dp[i] dp[i]为执行前 i i i个事件期望多久

    d p [ i ] = d p [ i − 1 ] + 1 + ( 1 − p [ i − 1 ] ) ∗ ( d p [ i ] − d p [ i − 2 ] ) dp[i] = dp[i-1]+1+(1-p[i-1])*(dp[i]-dp[i-2]) dp[i]=dp[i1]+1+(1p[i1])(dp[i]dp[i2])

    是不是很迷~

    d p [ i − 1 ] + 1 dp[i-1]+1 dp[i1]+1很好理解,就是继承前面的状态,且拿出一次机会来执行第 i i i件事

    有 p [ i − 1 ] 概 率 成 功 , 从 i − 1 转 移 到 i , 此 时 不 需 要 额 外 的 花 费 有p[i-1]概率成功,从i-1转移到i,此时不需要额外的花费 p[i1],i1i,

    有 1 − p [ i − 1 ] 概 率 失 败 , 从 i − 1 掉 到 了 i − 2 有1-p[i-1]概率失败,从i-1掉到了i-2 1p[i1],i1i2

    那 么 现 在 需 要 从 i − 2 转 移 到 i 那么现在需要从i-2转移到i i2i

    也 就 是 需 要 从 i − 2 转 移 到 i − 1 , 花 费 d p [ i − 1 ] − d p [ i − 2 ] 也就是需要从i-2转移到i-1,花费dp[i-1]-dp[i-2] i2i1,dp[i1]dp[i2]

    从 i − 1 转 移 到 i , 花 费 d p [ i ] − d p [ i − 1 ] 从i-1转移到i,花费dp[i]-dp[i-1] i1i,dp[i]dp[i1]

    相 加 花 费 得 到 上 面 的 式 子 相加花费得到上面的式子

    d p [ i ] dp[i] dp[i]移项可以得到

    d p [ i ] = d p [ i − 1 ] + 1 − ( 1 − p [ i − 1 ] ) ∗ d p [ i − 2 ] p [ i − 1 ] dp[i]=\frac{dp[i-1]+1-(1-p[i-1])*dp[i-2]}{p[i-1]} dp[i]=p[i1]dp[i1]+1(1p[i1])dp[i2]

    最后 d p [ n + 1 ] dp[n+1] dp[n+1]即位答案

    #include <bits/stdc++.h> using namespace std; const int maxn=2e5+10; int n; double dp[maxn],p[maxn]; int main() { cin >> n; for(int i=1;i<=n;i++) cin >> p[i]; dp[0]=dp[1]=0; for( int i=2;i<=n+1;i++ ) dp[i] = ( dp[i-1]+1.0-( 1.0-p[i-1] )*dp[i-2] )/p[i-1]; printf("%.3lf",dp[n+1]); }
    Processed: 0.011, SQL: 8