CF398B Painting The Wall 概率期望
阿新 • • 發佈:2018-12-28
思想 遞推 理解 pre bit main $1 open void
$$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$天這個事件就會發生,所以期望是概率的倒數。。。
不過這個也是可以證明的,只只要將計算式列出,做一個錯位相減,利用一下極限的思想,最後可以算出期望確實是概率的倒數。
題意:有一個 $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 }View Code
CF398B Painting The Wall 概率期望