zoukankan      html  css  js  c++  java
  • Foreign Postcards

    题意:

    给定 n 张排成一堆的的卡片,每一次从堆顶上等概率随机取出 [1~当前卡片数] 个卡片,如果堆顶的卡片是反面朝上,

    则将所有取出的卡片翻转,求问期望取出多少个反面朝上的卡片。

    解法:

    考虑dp,首先有期望的可加性得

    $ans = sum_{i=1}^n{ P(card_i  is  reversed  when  got) }$

    这样考虑求后面的概率。

    用 $f(i)$ 表示以 $i$ 为取出的卡片的顶上的卡片的概率。

    $f(1) = 1$

    $f(i) = sum{ frac{f(j)}{n-j+1} }$

    这样记$h(i,0), h(i,1)$ 分别表示第 $i$ 张卡片被一张正面朝上的卡消去 和 被一张反面朝上的卡消去的概率。

    从而有

    $$h(i,0) = sum_{1 leq j leq i, S(j-1) = C}{ f(j) frac{n-i+1}{n-j+1} }$$

    $h(i,1)$ 递推式同理。

    对两个式子记一下前缀和,$O(n)$

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    #define LD double
    #define N 1000010
    
    using namespace std;
    
    int n;
    LD f[N];
    char S[N];
    
    int main()
    {
        freopen("foreign.in", "r", stdin);
        freopen("foreign.out", "w", stdout);
        while(~scanf("%s",S))
        {
            n = strlen(S);
            f[1] = 1;
            f[2] = 1.0 / (LD)n;
            for(int i = 2;i < n;i++)
                f[i+1] = f[i] + f[i] / (n-i+1);
            LD sumC = 0, sumW = 0, ans = 0;
            for(int i = 1;i <= n;i++)
            {
                if(S[i-1] == 'C') sumC += f[i] / (n-i+1.0);
                else sumW += f[i] / (n-i+1.0);
                if(S[i-1] == 'C') ans += (n-i+1.0) * sumW;
                else ans += (n-i+1.0) * sumC;
            }
            printf("%.10lf
    ", ans);
        }
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    View Code
  • 相关阅读:
    2017寒假练习赛总结(实时更新)
    NOIP
    挖坑--总结
    BZOJ3709: [PA2014]Bohater
    BZOJ3714: [PA2014]Kuglarz
    BZOJ2276: [Poi2011]Temperature
    VIJOS P1543极值问题
    BZOJ2749: [HAOI2012]外星人
    BZOJ2173: 整数的lqp拆分
    BZOJ1100: [POI2007]对称轴osi
  • 原文地址:https://www.cnblogs.com/lawyer/p/6791722.html
Copyright © 2011-2022 走看看