牛客挑戰賽 38 C.圓桌聚餐(條件概率,貝葉斯公式,期望 dp,思維)

在這裏插入圖片描述


官方題解:
在這裏插入圖片描述

補充這個dp轉移的 概率係數 p(n2)p+(n4)q\displaystyle\frac{p}{(n - 2) * p + (n - 4) * q} 是如何求出的:

由於人數是無限的,題目告訴我們隨機抽取一個號碼的概率是 1n\frac{1}{n},實際上是告訴我們每個位置分配的概率是等可能的。

枚舉 A國人坐在第 i 個位置進行轉移,要求出他是A國人並且他坐在第 i 個位置的概率:注意這實際上是一個條件概率,他坐在第 i 個位置上是在他已經就坐這件事已經發生的基礎上發生的。

爲什麼這裏要用條件概率來進行轉移呢?
對於這題 dp 的決策,枚舉的轉移點是 :第一個坐下的人,他坐下的位置和他的國家,而不是某個到來的人他坐下的位置和他的國家,因爲這個到來的人不一定會坐下(例如他是A國人他就不會坐在 1 和 n 這個位置)這種情況是無法轉移的,無法轉移就表明這個 dpdp 有概率無解,這顯然不合理。

假設人數不是無限的,那麼有人就坐這件事就不是一定發生,對於沒有就坐的情況 dp[k] 不能由任何決策點轉移得到,因此dp[k] 可能是無解的。(這也是給出人數無限的意義)

因此,對於每個枚舉的轉移點,例如第一個坐下的人,他坐在第 i 個位置,並且他是A國人,需要求出一個概率 :P(他是A國人,並且他坐在第 i 個位置 | 有人就坐)

令 事件TA 表示:有人就坐, 事件 B1:他是A國人,事件B2:他是B國人。

假設當前枚舉的轉移點是:第一個坐下的人,他坐在第 i 個位置,並且他是 A 國人:先求出 P(B1 | A):坐下的這個人是A國人的概率,再除以 n2n - 2 就得到坐下的這個人是 A國人,並且他坐在第 i 個位置的概率(因爲在就坐已經發生的條件下,A 國人就坐這件事 樣本空間有 n - 2 個位置,每一個位置都是等可能的,因此每一個位置坐下的概率是 1n2\frac{1}{n - 2}

P(B1A)P(B_1 | A),在這個樣本空間中,事件 {B1,B2} 是一個完備事件組,考慮用貝葉斯公式得到這個概率值:P(B1A)=P(B1)P(AB1)i=1nP(Bi)P(ABi)P(B_1 | A) = \displaystyle\frac{P(B_1)*P(A|B_1)}{\sum_{i=1}^nP(B_i)*P(A|B_i)}

容易得出: P(AB1)=n2nP(A | B_1) = \frac{n - 2}{n}P(AB2)=n4nP(A|B_2) = \frac{n-4}{n}P(B1)=pp+q,P(B2)=qp+qP(B_1) =\frac{p}{p+q},P(B_2)=\frac{q}{p+q}

可以計算得到:P(B1A)=(n2)p(n2)p+(n4)qP(B_1|A) = \frac{(n-2)*p}{(n - 2) * p + (n - 4) * q}

同理可以得到:P(B2A)=(n4)q(n2)p+(n4)qP(B_2|A) = \frac{(n - 4) * q}{(n - 2)*p + (n - 4) * q}


代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
typedef long long ll;
const int mod = 998244353;
ll n,p,q;
ll dp[maxn],sum[maxn];
ll fpow(ll a,ll b) {
	ll r = 1;
	while (b) {
		if (b & 1) r = 1ll * r * a % mod;
		b >>= 1;
		a = 1ll * a * a % mod;
	}
	return r;
}
int main() {
	scanf("%lld%lld%lld",&n,&p,&q);
	dp[0] = dp[1] = dp[2] = 0;
	if (p) dp[3] = dp[4] = 1;
	for (int i = 1; i <= 4; i++)
		sum[i] = sum[i - 1] + dp[i];
	for (int i = 5; i <= n; i++) {
		dp[i] = (2 * sum[i - 2] * p % mod + 2 * sum[i - 3] * q % mod) % mod;
		ll t = (1ll * (i - 2) * p % mod + 1ll * (i - 4) * q % mod) % mod;
		dp[i] = (dp[i] * fpow(t,mod - 2) + 1) % mod;
		sum[i] = (sum[i - 1] + dp[i]) % mod;
	}
	printf("%lld\n",dp[n - 1] + 1);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章