牛客挑战赛 38 C.圆桌聚餐(条件概率,贝叶斯公式,期望 dp,思维)

在这里插入图片描述


官方题解:
在这里插入图片描述

补充这个dp转移的 概率系数 p ( n − 2 ) ∗ p + ( n − 4 ) ∗ q \displaystyle\frac{p}{(n - 2) * p + (n - 4) * q} (n2)p+(n4)qp 是如何求出的:

由于人数是无限的,题目告诉我们随机抽取一个号码的概率是 1 n \frac{1}{n} n1,实际上是告诉我们每个位置分配的概率是等可能的。

枚举 A国人坐在第 i 个位置进行转移,要求出他是A国人并且他坐在第 i 个位置的概率:注意这实际上是一个条件概率,他坐在第 i 个位置上是在他已经就坐这件事已经发生的基础上发生的。

为什么这里要用条件概率来进行转移呢?
对于这题 dp 的决策,枚举的转移点是 :第一个坐下的人,他坐下的位置和他的国家,而不是某个到来的人他坐下的位置和他的国家,因为这个到来的人不一定会坐下(例如他是A国人他就不会坐在 1 和 n 这个位置)这种情况是无法转移的,无法转移就表明这个 d p dp dp 有概率无解,这显然不合理。

假设人数不是无限的,那么有人就坐这件事就不是一定发生,对于没有就坐的情况 dp[k] 不能由任何决策点转移得到,因此dp[k] 可能是无解的。(这也是给出人数无限的意义)

因此,对于每个枚举的转移点,例如第一个坐下的人,他坐在第 i 个位置,并且他是A国人,需要求出一个概率 :P(他是A国人,并且他坐在第 i 个位置 | 有人就坐)

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

假设当前枚举的转移点是:第一个坐下的人,他坐在第 i 个位置,并且他是 A 国人:先求出 P(B1 | A):坐下的这个人是A国人的概率,再除以 n − 2 n - 2 n2 就得到坐下的这个人是 A国人,并且他坐在第 i 个位置的概率(因为在就坐已经发生的条件下,A 国人就坐这件事 样本空间有 n - 2 个位置,每一个位置都是等可能的,因此每一个位置坐下的概率是 1 n − 2 \frac{1}{n - 2} n21

P ( B 1 ∣ A ) P(B_1 | A) P(B1A),在这个样本空间中,事件 {B1,B2} 是一个完备事件组,考虑用贝叶斯公式得到这个概率值: P ( B 1 ∣ A ) = P ( B 1 ) ∗ P ( A ∣ B 1 ) ∑ i = 1 n P ( B i ) ∗ P ( A ∣ B i ) P(B_1 | A) = \displaystyle\frac{P(B_1)*P(A|B_1)}{\sum_{i=1}^nP(B_i)*P(A|B_i)} P(B1A)=i=1nP(Bi)P(ABi)P(B1)P(AB1)

容易得出: P ( A ∣ B 1 ) = n − 2 n P(A | B_1) = \frac{n - 2}{n} P(AB1)=nn2 P ( A ∣ B 2 ) = n − 4 n P(A|B_2) = \frac{n-4}{n} P(AB2)=nn4 P ( B 1 ) = p p + q , P ( B 2 ) = q p + q P(B_1) =\frac{p}{p+q},P(B_2)=\frac{q}{p+q} P(B1)=p+qp,P(B2)=p+qq

可以计算得到: P ( B 1 ∣ A ) = ( n − 2 ) ∗ p ( n − 2 ) ∗ p + ( n − 4 ) ∗ q P(B_1|A) = \frac{(n-2)*p}{(n - 2) * p + (n - 4) * q} P(B1A)=(n2)p+(n4)q(n2)p

同理可以得到: P ( B 2 ∣ A ) = ( n − 4 ) ∗ q ( n − 2 ) ∗ p + ( n − 4 ) ∗ q P(B_2|A) = \frac{(n - 4) * q}{(n - 2)*p + (n - 4) * q} P(B2A)=(n2)p+(n4)q(n4)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);
}

猜你喜欢

转载自blog.csdn.net/qq_41997978/article/details/105053785