CF398B Painting The Wall 概率期望

题意:有一个 $n * n$ 的网格,其中 $m$ 个格子上涂了色。每次随机选择一个格子涂色,允许重复涂,求让网格每一行每一列都至少有一个格子涂了色的操作次数期望。
题解:,,这种一般都要倒推才行。
设$f[i][j]$表示还有$i$行,$j$列未满足的情况下的期望次数。
因为每次选择都是完全随机,不受其他东西的影响。
所以对于题中给出的$m$,实际上就是告诉了我们要求什么东西,假设在已经有那$m$个涂色方块的情况下,我们还有$t1$行,$t2$列未满足,那么我们要求的就是$f[t1][t2]$.
那么我们可以列出转移方程:(一行写不下,分2行写)
$$f[i][j] = 1 + \frac{ij}{n ^ 2} f[i - 1][j - 1] + \frac{(n - i)j}{n ^ 2} f[i][j - 1] $$
$$f[i][j] += \frac{i(n - j)}{n ^ 2} f[i - 1][j] + \frac{(n - i)(n - j)}{n^2} f[i][j]$$
$1$是每次选择的代价,后面的就是进入每一种状态的概率,对于任意后继状态,它对当前状态的贡献就是它的期望 * 进入这个状态的概率(全期望公式)

然后移项化简,对于后面这一堆东西提出一个$\frac{1}{n ^ 2}$,然后把$f[i][j]$放到等式左边,这样就只需要在最后面除一次,可以降低一点精度误差?
$$f[i][j] = \frac{n ^ 2 + ijf[i - 1][j - 1] + (n - i)jf[i][j - 1] + i(n - j)f[i - 1][j]}{[n ^ 2 - (n - i) (n - j)]}$$
然后因为计算的时候,可能会出现为满足行或列的数量为0的情况,这种时候还放在一起计算就不太方便了(需要特判),因此考虑把这些情况单独拿出来看。
那么因为$f[i][0]$这个状态之受行的影响,所以可以看做一个优惠券收集问题,即:
$$f[i][0] = \sum_{j = 1}^{i} \frac{n}{j}$$
那么由于$$f[i - 1][0] = \sum_{j = 1}^{i - 1} \frac{n}{j}$$
可以得到关于$f[i][0]$和$f[i - 1][0]$的一个递推式,即:
$$f[i][0] = f[i - 1][0] + \frac{n}{i}$$
解释一下那个和式:如果我们现在还有$i$行未满足,共$n$行,那么选一次可以导致一行新的被满足的概率就是$\frac{i}{n}$,那么期望就为$\frac{n}{i}$.
这个东西的感性理解大概是:如果一个事件发生的概率是$\frac{1}{5}$,那么显然期望$5$天这个事件就会发生,所以期望是概率的倒数。。。
不过这个也是可以证明的,只只要将计算式列出,做一个错位相减,利用一下极限的思想,最后可以算出期望确实是概率的倒数。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define R register int
 4 #define AC 2200
 5 #define db double
 6
 7 int n, m, l, r;
 8 double f[AC][AC];
 9 bool zl[AC], zr[AC];//表示第i行or第i列有没有被标记
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 void pre()
20 {
21     n = l = r = read(), m = read();
22     for(R i = 1; i <= m; i ++)
23     {
24         int x = read(), y = read();
25         if(!zl[x]) zl[x] = true, -- l;
26         if(!zr[y]) zr[y] = true, -- r;
27     }
28 }
29
30 double cal(double x, double y){
31     return x / y;
32 }
33
34 void work()
35 {//因为把i or j为0的状态放在下面一起枚举不太方便(要特判),所以在前面单独求
36     for(R i = 1; i <= n; i ++)//
37     {
38         f[i][0] = f[i - 1][0] + (double)n / i;//因为这个时候只有行的影响,所以只需要考虑行,那么就相当于一个购物券收集问题
39         f[0][i] = f[0][i - 1] + (double)n / i;
40     }
41     for(R i = 1; i <= l; i ++)
42         for(R j = 1; j <= r; j ++)
43         {
44             /*f[i][j] = 1;
45             f[i][j] += cal(i * j, n * n) * f[i - 1][j - 1];
46             f[i][j] += cal((n - i) * j, n * n) * f[i][j - 1];
47             f[i][j] += cal(i * (n - j), n * n) * f[i - 1][j];
48             f[i][j] /= 1 - cal((n - i) * (n - j), n * n);*/
49             f[i][j] = n * n;//把除法放在最后以降低精度误差
50             f[i][j] += i * j * f[i - 1][j - 1];
51             f[i][j] += (n - i) * j * f[i][j - 1];
52             f[i][j] += i * (n - j) * f[i - 1][j];
53             f[i][j] /= n * n - (n - i) * (n - j);
54         }
55     printf("%.10lf\n", f[l][r]);
56 }
57
58 int main()
59 {
60     freopen("in.in", "r", stdin);
61     pre();
62     work();
63     fclose(stdin);
64     return 0;
65 }

原文地址:https://www.cnblogs.com/ww3113306/p/10192517.html

时间: 2024-10-20 11:37:30

CF398B Painting The Wall 概率期望的相关文章

Codeforces Round #233 (Div. 2)D. Painting The Wall 概率DP

                                                                               D. Painting The Wall User ainta decided to paint a wall. The wall consists of n2 tiles, that are arranged in an n × n table. Some tiles are painted, and the others are not

cf 398B. Painting The Wall【期望dp】

传送门:http://codeforces.com/problemset/problem/398/B Description: User ainta decided to paint a wall. The wall consists of n2 tiles, that are arranged in an n?×?n table. Some tiles are painted, and the others are not. As he wants to paint it beautifull

[Codefoeces398B]Painting The Wall(概率DP)

题目大意:一个$n\times n$的棋盘,其中有$m$个格子已经被染色,执行一次染色操作(无论选择的格子是否已被染色)消耗一个单位时间,染色时选中每个格子的概率均等,求使每一行.每一列都存在被染色的格子的期望用时. 传送门 显然,被染色的砖的位置对解题是没有影响的,我们可以将已染色砖所在的行和列移动到右下角,问题就转化到了在更小棋盘中的新问题. 在任一时刻,棋盘内的状态如下: 其中绿色区域为当前问题的棋盘,选中对行和列都有贡献: 选中黄色对行或列有贡献: 选中红色没有贡献: 设$f[i][j]

hdu 4586 (概率+期望)

http://acm.hdu.edu.cn/showproblem.php?pid=4586 大致题意:有一个骰子有n个面,掷到每一个面的概率是相等的,每一个面上都有相应的钱数.其中当你掷到m个面之一时,你有多掷一次的机会.问最后所得钱数的期望. 思路:设投掷第一次的期望是p,那么第二次的期望是m/n*p,第三次的期望是 (m/n)^2*p......第N次的期望是(m/n)^(N-1)*p. 那么这些期望之和便是答案.之前也是想到这,但不知道如何处理无限的情况.当时脑卡了,这不是赤裸裸的等比数

OI队内测试一【数论概率期望】

版权声明:未经本人允许,擅自转载,一旦发现将严肃处理,情节严重者,将追究法律责任! 测试分数:110 本应分数:160 改完分数:200 T1: 题解:推出了一个初始式子但是n的4分之3次方 忘了合并[实际上是没发现]本来应有60分的,但是忘记开long long 只有30分 因为一些公式不好写出来就直接截图题解吧! T2: 题解:很简单的概率期望,算出每个点被选的概率,然后在上树状数组或者线段树求逆序队,但是我只有80分,为什么解法不行?NO NO 你还是太年轻我只是线段树数据范围开小了!![

uvalive 7331 Hovering Hornet 半平面交+概率期望

题意:一个骰子在一个人正方形内,蜜蜂在任意一个位置可以出现,问看到点数的期望. 思路:半平面交+概率期望 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdlib> 6 #include<string> 7 #include<cmath> 8 #include<vector&

【BZOJ-1419】Red is good 概率期望DP

1419: Red is good Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 660  Solved: 257[Submit][Status][Discuss] Description 桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元.可以随时停止翻牌,在最优策略下平均能得到多少钱. Input 一行输入两个数R,B,其值在0到5000之间 Output 在最优策略下平均能得到多少钱

Lightoj 1027 概率期望

Problem: 概率期望 Analyse: 非常经典的带有递归实现,的方程期望式子. E为期望,z为正数个数,zp为正数平均值,f为负数个数,fp为负数平均值. z?zpn+f?fp+En=E /**********************jibancanyang************************** *Author* :jibancanyang *Created Time* : 五 5/ 6 23:58:46 2016 *File Name* : .cpp **Code**:

hdu4405--Aeroplane chess+概率期望dp

首先推荐一篇很好的如何概率期望问题的入门文章:点击打开链接 昨天比赛的时候面对这道题的第一想法是依照数学期望的定义来做,即依次求出某个点扔i次骰子能到达n点的概率,然后由期望的定义就可以求出答案了.但显然这在程序上是不可能实现的. 今天看了那篇文章后才知道自己的想法是大错特错的;求解这种问题应该采用一种递推的思路,即每次只考虑一次转移后当前状态的期望,然后我们依次考虑每个节点就可以得到一个方程组,然后就只需要求解这个方程组就行了. 当然对于如何求解这个方程组,我们可以采用高斯消元法,当然如果这个