HDU4870 Rating(概率)


第一場多校,感覺自己都跳去看坑自己的題目里去了,很多自己可能會比較擅長一點的題目沒看,然后寫一下其中一道概率題的題解吧,感覺和自己前幾天做的概率dp的思路是一樣的。下面先來看題意:一個人有兩個TC的賬號,一開始兩個賬號rating都是0,然后每次它會選擇里面rating較小的一個賬號去打比賽,每次比賽有p的概率+1分,有1-p的概率-2分,當然如果本身是<=2分的也就還是回到0分。然后問最后其中一個賬號到達20分時需要打多少次比賽。

先考慮一場比賽的情況,定義dp[k]為當前為k分,要達到20分時的期望回合數。(令q=1-p)

那么顯然有 dp[0]=1+p*dp[1]+q*dp[0] 化簡得 dp[0]=1/p+dp[1]

               dp[1]=1+p*dp[2]+q*dp[0] 化簡得 dp[0]=1/p+1/p^2+dp[2]

我們令  dp[0]=tk+dp[k] 那么tk就表示由0狀態到達k狀態所需的期望回合數。那么顯然如果是要到達20分的話,答案就是t20

然后我們看   dp[k]=1+p*dp[k+1]+q*dp[k-2]  代入dp[0]=dp[k]+tk 就有

dp[0]=1/p+1/p*t[k]-(1-p)/p*t[k-2]+dp[k+1]  

所以  t[k+1]=1/p+1/p*t[k]-(1-p)/p*t[k-2]

邊界條件是  t[0]=0,t[1]=1/p,t[2]=1/p+1/p^2  

知道這些就可以遞推出所有需要的t[k]了。

現在我們來看如果有兩個賬號怎么破。首先我們必然是 (0,0)->(0,1)->(1,1)->(1,2)->(2,2)->(2,3)->(3,3)...

(0,0)->(0,1)需要的期望回合數是t[1]-t[0].  (0,1)->(1,1)需要的期望回合數是 t[1]-t[0]

(1,1)->(1,2)需要的期望回合數是t[2]-t[1].  (1,2)->(2,2)需要的期望回合數是 t[2]-t[1].

....

(18,18)->(18,19)需要的期望回合數是t[19]-t[18]. (18,19)->(19,19)需要的期望回合數是t[19]-t[18].  

(19,19)->(19,20)需要的期望回合數是t[20]-t[19]。

全部加起來的結果就是t[19]*2+t[20]-t[19].

所以最后的復雜度可以是線性的,而且理論上對於k個賬號也是適用的,這樣就可以避開了高斯消元的做法了。

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#define ll long long
#define maxn 10000
#define maxe 30000
#define inf 0x3f3f3f3f
using namespace std;

double p;

double t[25];

int main()
{
	while (cin >> p){
		t[0] = 0;
		t[1] = 1 / p;
		t[2] = 1 / p + 1 / (p*p);
		for (int i = 3; i <= 20; i++){
			t[i] = 1 / p + 1 / p*t[i - 1] - (1 - p) / p*t[i - 3];
		}
		double ans = t[19] * 2 + t[20] - t[19];
		printf("%.6lf\n", ans);
	}
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM