CF623D birthday 贪心 概率期望
题意:n个人,玩抓人游戏,每抓住一个人都要猜这个人是谁。对于每一局,第i个人有$p_{i}$的概率被抓到。游戏结束当且仅当每个人都在某局中被抓到并且猜中自己的名字,求一个合适的策略来使得期望游戏局数最少,输出这个期望最少局数.
题解:设$g[i]$表示到$i$局为止,已经全部被猜中过的概率,$f[i][x]$表示到第$i$局为止,已经猜中过第$x$个人的概率。
那么有$$ans = \sum_{i = 1}^{\infty} (g[i] - g[i - 1])i$$
随游戏局数增长,$g[x]$会趋近于1,要让期望最小,显然在$x$越小时,要让$g[x] - g[x - 1]$越大越好,即$g[x]$增长的越快越好。
若在第$i$局猜被抓到的是$k$,那么有:
$f[i][x] = \begin{cases}
f[i - 1][x] + (1 - f[i - 1][x]) p_{x} \quad x == k\\
f[i - 1][x] \quad x != k
\end{cases}$
$g[x] = g[x - 1] \frac{f[x][k]}{f[x - 1][k]}($因为只有$f[x][k]$变化了)
因此我们只需要让$\frac{f[x][k]}{f[x - 1][k]}$最大即可。
$$\frac{f[x][k]}{f[x - 1][k]} = \frac{f[x - 1][k] + (1 - f[x - 1][k])p_{k}}{f[x - 1][k]} = 1 + \frac{(1 - f[x - 1][k])p_{k}}{f[x - 1][k]}$$
所以要使$\frac{(1 - f[x - 1][k])p_{k}}{f[x - 1][k]}$最大。
因此我们枚举$k$,贪心的找最优策略并更新答案,大约$3e5$次可以满足精度要求
这里注意为了满足初始化的要求(在没有把n个人都猜过之前,是没有概率全部猜中的),所以要在最开始先把n个人都猜一遍,然后再继续贪心
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 110 5 #define ld double 6 7 int n; 8 ld ans, last, g; 9 ld f[AC], p[AC]; 10 11 inline int read() 12 { 13 int x = 0;char c = getchar(); 14 while(c > '9' || c < '0') c = getchar(); 15 while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); 16 return x; 17 } 18 19 ld cal(int x){ 20 return f[x] + 1.0 * (1 - f[x]) * p[x]; 21 } 22 23 void pre() 24 { 25 n = read(), last = 1; 26 for(R i = 1; i <= n; i ++) 27 f[i] = p[i] = 1.0 * read() / 100.0, last *= p[i];//根据转移式来的 28 ans = n * last;//因为只有猜过所有人之后才有可能结束游戏。。。 29 } 30 31 /* int x = 0; ld maxn = 0; 32 for(R j = 1; j <= n; j ++) 33 { 34 ld now = cal(j); 35 if(cal(j) / f[j] > maxn) maxn = now, x = j; 36 } */ 37 void work()//为了解决初始化问题,,,先把所有人都猜一遍 38 { 39 for(R i = n + 1; i <= 300000; i ++) 40 { 41 int x = 1; //x不能默认为1,不然f[x]就为0了,,,, 42 for(R j = 1; j <= n; j ++) 43 if(cal(j) / f[j] > cal(x) / f[x]) x = j; 44 g = last * cal(x) / f[x], f[x] = cal(x); 45 ans += i * (g - last), last = g; 46 } 47 printf("%.10lf\n", ans); 48 } 49 50 int main() 51 { 52 freopen("in.in", "r", stdin); 53 pre(); 54 work(); 55 fclose(stdin); 56 return 0; 57 }