一個\(n \times m\)的矩形空間,起點是\((1,1)\),終點是\((n,m)\)。c++
假設當前位於\((x,y)\):spa
矩形空間中有一個小的矩形黑洞,用左上角和右下角的座標表示,走進黑洞視爲遊戲失敗,走到\((n,m)\)視爲遊戲成功,問遊戲成功的機率。code
先不考慮黑洞。blog
對於\(1 \leq x < n, 1 \leq y < m\),走到\((x,y)\)一共有\(C_{x+y-2}^{x-1}\)種可能的路徑,而後走每一條可能的路徑的機率爲\(\frac{1}{2^{x+y-2}}\),因此走到\((x,y)\)的機率是\(\frac{C_{x+y-2}^{x-1}}{2^{x+y-2}}\)。遊戲
可是\(n,m\)的取值最高能夠到\(1e5\),若是不加處理會炸精度,若是使用\(\log\)處理就能夠把數值壓在能接受的範圍內。再加上it
\(O(n)\)預處理出\(\log(i!)\)後就能夠方便的計算\(P(x,y)\)了。class
而後根據規則,最後一行和最後一列的機率要另外算。這裏僅以最後一行爲例,最後一列也是用一樣的方法。方法
記走到\((x,y)\)的機率爲\(P(x,y)\),那麼若是\((x,y)\)位於最後一行,則\(P(x,y)=P(x,y-1)+\frac{1}{2}P(x-1,y)\)。而後\(P(1,n)\)很容易推出等於\(\frac{1}{2^{n-1}}\),因此這一行的機率就能夠\(O(n)\)的遞推出來。im
假設上圖中,黑色部分爲黑洞,\((1,1)\)位於坐上角,那麼很容易就能夠得出遊戲成功的機率爲走到灰色格子的機率之和。將以前推導出的公式代入便可。總結
早上七點的比賽差點錯過了。前三題幾乎都是直接秒,可是卡在了第四題。公式都推對了,可是沒有想到炸精度怎麼處理。腦海中出現了以前llg想在學校月賽搞用log處理大數的出題思路,可是看精度一直以爲不太行,而後就下班了,哪想到這就是正解。果真有時候就應該xjbg。
而後補題的時候又是由於擔憂精度問題用了long double,而後各類TLE,換成double就過了。
#include<bits/stdc++.h> using namespace std; const int N = 2e5 + 5; double lg[N], lstr[N], lstc[N]; int main() { #ifdef BACKLIGHT freopen("in.txt", "r", stdin); #endif lg[0] = 0; for (int i =1; i <= 2e5; ++i) lg[i] = lg[i-1] + log2(i); int T; scanf("%d", &T); for (int Case = 1; Case <= T; Case ++) { int n, m, l, r, u, d; scanf("%d %d %d %d %d %d", &n, &m, &l, &u, &r, &d); lstr[1] = pow(2, lg[1 + n - 2] - lg[1 - 1] - lg[n - 1] - 1 - n + 2); for (int i = 2; i <= m; i++) { lstr[i] = lstr[i-1] + 0.5 * pow(2, lg[i + (n-1)- 2] - lg[i - 1] - lg[(n-1) - 1] - i - (n-1) + 2); } lstc[1] = pow(2, lg[1 + m - 2] - lg[1 - 1] - lg[m - 1] - 1 - m + 2); for (int i = 2; i <= n; i++) { lstc[i] = lstc[i-1] + 0.5 * pow(2, lg[i + (m-1)- 2] - lg[i - 1] - lg[(m-1) - 1] - i - (m-1) + 2); } double ans = 0, tmp; for (int i = 1; i <= l - 1; ++i) { int D = l + d - i; if(D > m) continue; else if(D == m) { ans += lstc[i]; } else { tmp = lg[i + D - 2] - lg[i - 1] - lg[D - 1] - i - D + 2; ans += pow(2, tmp); } } for (int i = 1; i <= u - 1; ++i) { int R = r + u - i; if(R > n) continue; else if(R == n) { ans += lstr[i]; } else { tmp = lg[i + R - 2] - lg[i - 1] - lg[R - 1] - i - R + 2; ans += pow(2, tmp); } } printf("Case #%d: %.12lf\n", Case, ans); } return 0; }