題意: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 #include2view codeusing
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