Codeforces Round #105 (Div. 2) D. Bag of mice

Codeforces Round #105 (Div. 2)

翻译 岛田小雅

D. Bag of mice

出题人 Nickolas

巨龙和公主在纠结大年夜应该干什么。巨龙想去山上看精灵们在月光下跳舞,但公主只想早点睡觉。他们希望能够和谐友善地达成共识,于是决定将选择权交给命运。

一个口袋里有 \(w\) 个白老鼠和 \(b\) 个黑老鼠。巨龙和公主轮流从口袋里抽老鼠,谁先抽到白老鼠谁就获胜。每次巨龙抽老鼠时,口袋里总会有一只老鼠被吓得跳出去(公主不会惊吓到老鼠)。已知公主先抽。那么她获胜的概率有多大呢?

如果口袋里没有老鼠了,但谁都没有抽到白老鼠,那么巨龙获胜。从口袋里跳出来的老鼠不算被抽走的老鼠,也就是说它们不会直接决定获胜者。如果一只老鼠跳出去了,那么它就不会再回口袋里。口袋里的每只老鼠被抽走的概率都是一样的。

输入格式

输入只有一行,两个整型 \(w\)\(b\) \((0\leqslant{w,b}\leqslant{1000})\)

输出格式

输出公主获胜的概率。只要与标准答案相差不超过 \(10^{-9}\) 都算作正确答案。

样例 1

输入

1 3

输出

0.500000000

样例 2

输入

5 5

输出

0.658730159

补充

对样例 \(1\) 而言,第一轮公主抽中白老鼠并获胜的概率是 \(\frac{1}{4}\),巨龙抽到黑老鼠游戏继续的概率是 \(\frac{3}{4}\times{\frac{2}{3}}=\frac{1}{2}\)。第一轮结束后,口袋里还剩 \(2\) 只老鼠,一只白的和一只黑的,其中一只会被巨龙吓得跳出口袋,然后公主会在下一轮抽出剩下的最后一只。如果公主抽到白老鼠,那她获胜(概率是 \(\frac{1}{2}\times{\frac{1}{2}}=\frac{1}{4}\)),否则没人能抽到白老鼠,那么巨龙获胜。

题解

作者 岛田小雅

为了做一道概率 DP 题OI Wiki 跳到这道题来从头学起。

\(f_{i,j}\) 来表示轮到公主时还剩下 \(i\) 只白老鼠和 \(j\) 只黑老鼠时公主赢的概率,这样维护数组 \(f\) 时,就能让 \(f_{i,j}\) “收集”自己之后所有公主获胜的概率。

对每轮:

  • 公主抓到白鼠,公主获胜,概率为:\(\frac{i}{i+j}\) \((i+j>0)\)
  • 公主抓到黑鼠,巨龙抓到白鼠,巨龙获胜,概率为:\(\frac{i}{i+j}\times{\frac{i}{i+j-1}}\) \((i\geqslant{1},j\geqslant{1})\)
  • 公主抓到黑鼠,巨龙抓到黑鼠,跑出黑鼠,最终公主获胜,概率为:\(\frac{j}{i+j}\times{\frac{j-1}{i+j-1}}\times{\frac{j-2}{i+j-2}}\times{f_{i,j-3}}\) \((j\geqslant{3})\)
  • 公主抓到黑鼠,巨龙抓到黑鼠,跑出白鼠,最终公主获胜,概率为:\(\frac{j}{i+j}\times{\frac{j-1}{i+j-1}}\times{\frac{i}{i+j-2}}\times{f_{i-1,j-2}}\) \((i\geqslant{1},j\geqslant{2})\)

维护 \(f_{i,j}\) 时,我们只需要转移 \(1,3,4\) 这三种情况的概率即可 。

AC 代码

作者 岛田小雅
#include <bits/stdc++.h>
using namespace std;

const int N = 1e3+1;
int w, b;
double f[N][N];

int main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cout << setiosflags(ios::fixed) << setprecision(9); 
    cin >> w >> b;
    for(int i = 0; i <= w; i++)
    {
        for(int j = 0; j <= b; j++)
        {
            if(i+j > 0) f[i][j] = (double)i/(i+j);
            if(j >= 3) f[i][j] += f[i][j-3]*j/(i+j)*(j-1)/(i+j-1)*(j-2)/(i+j-2);
            if(i>=1 && j>=2) f[i][j] += f[i-1][j-2]*j/(i+j)*(j-1)/(i+j-1)*i/(i+j-2);
        }
    }
    cout << f[w][b];
    return 0;
}
posted @ 2022-09-27 01:23  岛田小雅  阅读(29)  评论(0编辑  收藏  举报