CF623D birthday 貪心 概率期望

2022-04-29 21:15:11 字數 1339 閱讀 4383

題意:n個人,玩抓人遊戲,每抓住乙個人都要猜這個人是誰。對於每一局,第i個人有$p_$的概率被抓到。遊戲結束當且僅當每個人都在某局中被抓到並且猜中自己的名字,求乙個合適的策略來使得期望遊戲局數最少,輸出這個期望最少局數.

題解:設$g[i]$表示到$i$局為止,已經全部被猜中過的概率,$f[i][x]$表示到第$i$局為止,已經猜中過第$x$個人的概率。

那麼有$$ans = \sum_^ (g[i] - g[i - 1])i$$

隨遊戲局數增長,$g[x]$會趨近於1,要讓期望最小,顯然在$x$越小時,要讓$g[x] - g[x - 1]$越大越好,即$g[x]$增長的越快越好。

若在第$i$局猜被抓到的是$k$,那麼有:

$f[i][x] = \begin

f[i - 1][x] + (1 - f[i - 1][x]) p_ \quad x == k\\

f[i - 1][x] \quad x != k

\end$

$g[x] = g[x - 1] \frac($因為只有$f[x][k]$變化了)

因此我們只需要讓$\frac$最大即可。

$$\frac = \frac} = 1 + \frac}$$

所以要使$\frac}$最大。

因此我們列舉$k$,貪心的找最優策略並更新答案,大約$3e5$次可以滿足精度要求

這裡注意為了滿足初始化的要求(在沒有把n個人都猜過之前,是沒有概率全部猜中的),所以要在最開始先把n個人都猜一遍,然後再繼續貪心

1 #include2

using

namespace

std;

3#define r register int

4#define ac 110

5#define ld double 67

intn;

8ld ans, last, g;

9ld f[ac], p[ac];

1011 inline int

read()

1218

19 ld cal(int

x)22

23void

pre()

2430

31/*

int x = 0; ld maxn = 0;

32for(r j = 1; j <= n; j ++)

33

*/37

void work()//

為了解決初始化問題,,,先把所有人都猜一遍

3847 printf("

%.10lf\n

", ans);48}

4950

intmain()

51

view code