2021牛客暑期多校训练营4 B题

B题: Sample Game

原题链接:https://ac.nowcoder.com/acm/contest/11255/B

题目大意

有一个可以生成 1 1 1 n ( 1 ≤ n ≤ 100 ) n(1\le n\le 100) n(1n100) 之间的随机数的生成器,生成 x ( 1 ≤ x ≤ n ) x(1\le x\le n) x(1xn) 的概率为 p x p_x px
现在依次执行以下操作:
①:随机生成一个数 x x x ;
②:若 x x x 是已生成的数中最大的,则执行步骤①,否则执行步骤③;
③:若共生成了 y y y 个数字,则获得分数 y 2 y ^2 y2 ;
求获得分数的期望值
题目给出整数 w i ( 1 ≤ i ≤ n ) w_i(1\le i\le n) wi(1in) p i = w i ∑ j = 1 n w j p_i=\frac{w_i}{\sum^n_{j=1}w_j} pi=j=1nwjwi
答案对 998244353 998244353 998244353 取模,若出现分数请计算逆元。

题解

对于求期望值的问题,我们优先考虑使用期望dp处理,采用倒推。
直接考虑 E ( y 2 ) E(y^2) E(y2) 的形式较为困难,我们可以从 E ( y ) E(y) E(y) 开始考虑。
我们设 f x f_x fx 表示随机得到 x x x 后的期望剩余抽取数字次数,我们将此时下一次抽取数字 a a a 的情况分类讨论:
a < x a<x a<x :将执行步骤③,直接结束,剩余回合数为 0 0 0 ,发生概率为 p a p_a pa ,总期望为 ∑ i = 1 x − 1 p i \sum\limits^{x-1}_{i=1}p_i i=1x1pi ;
a = x a=x a=x :将执行步骤①,继续抽取数字,剩余回合数为 f x f_x fx ,发生概率为 p x p_x px ,期望为 p x ( 1 + f x ) p_x(1+f_x) px(1+fx) ;(该种情况其实可以并入③中讨论,分离出是为了下文化简方便)
a > x a>x a>x :将执行步骤①,继续抽取数字,剩余回合数为 f a f_a fa ,发生概率为 p a p_a pa ,总期望为 ∑ i = x + 1 n p i ( 1 + f i ) \sum\limits^n_{i=x+1}p_i(1+f_i) i=x+1npi(1+fi) ;
将以上三种情况合并,我们可以初步得到转移式为:
f x = ∑ i = 1 x − 1 p i + p x ( 1 + f x ) + ∑ i = x + 1 n p i ( 1 + f i ) f_x=\sum^{x-1}_{i=1}p_i+p_x(1+f_x)+\sum^n_{i=x+1}p_i(1+f_i) fx=i=1x1pi+px(1+fx)+i=x+1npi(1+fi)

观察到等式右侧也有 f x f_x fx ,我们将其移到等式左侧合并:
( 1 − p x ) f x = ∑ i = 1 x − 1 p i + p x + ∑ i = x + 1 n p i ( 1 + f i ) (1-p_x)f_x=\sum^{x-1}_{i=1}p_i+p_x+\sum^n_{i=x+1}p_i(1+f_i) (1px)fx=i=1x1pi+px+i=x+1npi(1+fi)

发现右侧包含所有 p i ( 1 ≤ i ≤ n ) p_i(1\le i\le n) pi(1in) (即全部分项概率,总和为 1 1 1 ),继续化简:
( 1 − p x ) f x = 1 + ∑ i = x + 1 n p i f i (1-p_x)f_x=1+\sum^n_{i=x+1}p_if_i (1px)fx=1+i=x+1npifi

化简系数为 1 1 1 ,得到最终转移式:
f x = 1 + ∑ i = x + 1 n p i f i 1 − p x f_x=\frac{1+\sum\limits^n_{i=x+1}p_if_i}{1-p_x} fx=1px1+i=x+1npifi

然后我们考虑构造转化 E ( y 2 ) E(y^2) E(y2) 的形式的转移式。
根据期望的性质,显而易见的, E ( y 2 ) E(y^2) E(y2) 并不一定与 E 2 ( y ) E^2(y) E2(y) 相等,但是我们可将 E ( ( y + 1 ) 2 ) E((y+1)^2) E((y+1)2) 转化为 E ( y 2 + 2 y + 1 ) E(y^2+2y+1) E(y2+2y+1) (即完全平方公式),然后拆分为 E ( y 2 ) + E ( 2 y ) + E ( 1 ) E(y^2)+E(2y)+E(1) E(y2)+E(2y)+E(1) ,化简可得 E ( y 2 ) + 2 E ( y ) + 1 E(y^2)+2E(y)+1 E(y2)+2E(y)+1
我们设 g x g_x gx 表示随机得到 x x x 后的期望分数(即 剩 余 回 合 数 2 剩余回合数^2 2 ),我们将此时下一次抽取数字 a a a 的情况分类讨论:
a < x a<x a<x :将执行步骤③,直接结束,剩余回合数为 0 0 0 ,发生概率为 p a p_a pa ,总期望为 ∑ i = 1 x − 1 p i \sum\limits^{x-1}_{i=1}p_i i=1x1pi ;
a = x a=x a=x :将执行步骤①,继续抽取数字,剩余回合数为 f x f_x fx ,发生概率为 p x p_x px ,期望为 p x ( 1 + f x ) 2 p_x(1+f_x)^2 px(1+fx)2 ,根据上文拆分规则可化简为 p x ( 1 + 2 f x + g x ) p_x(1+2f_x+g_x) px(1+2fx+gx) ;(该种情况其实可以并入③中讨论,分离出是为了下文化简方便)
a > x a>x a>x :将执行步骤①,继续抽取数字,剩余回合数为 f a f_a fa ,发生概率为 p a p_a pa ,总期望为 ∑ i = x + 1 n p i ( 1 + f i ) 2 \sum\limits^n_{i=x+1}p_i(1+f_i)^2 i=x+1npi(1+fi)2 ,根据上文拆分规则可化简为 ∑ i = x + 1 n p i ( 1 + 2 f i + g i ) \sum\limits^n_{i=x+1}p_i(1+2f_i+g_i) i=x+1npi(1+2fi+gi) ;
将以上三种情况合并,我们可以初步得到转移式为:
g x = ∑ i = 1 x − 1 p i + p x ( 1 + 2 f x + g x ) + ∑ i = x + 1 n p i ( 1 + 2 f i + g x ) g_x=\sum^{x-1}_{i=1}p_i+p_x(1+2f_x+g_x)+\sum^n_{i=x+1}p_i(1+2f_i+g_x) gx=i=1x1pi+px(1+2fx+gx)+i=x+1npi(1+2fi+gx)

观察到等式右侧也有 g x g_x gx ,我们将其移到等式左侧合并:
( 1 − p x ) g x = ∑ i = 1 x − 1 p i + p x + 2 p x f x + ∑ i = x + 1 n p i ( 1 + 2 f i + g i ) (1-p_x)g_x=\sum^{x-1}_{i=1}p_i+p_x+2p_xf_x+\sum^n_{i=x+1}p_i(1+2f_i+g_i) (1px)gx=i=1x1pi+px+2pxfx+i=x+1npi(1+2fi+gi)

发现右侧包含所有 p i ( 1 ≤ i ≤ n ) p_i(1\le i\le n) pi(1in) (即全部分项概率,总和为 1 1 1 ),继续化简:
( 1 − p x ) f x = 1 + 2 p x f x + ∑ i = x + 1 n p i ( 2 f i + g i ) (1-p_x)f_x=1+2p_xf_x+\sum^n_{i=x+1}p_i(2f_i+g_i) (1px)fx=1+2pxfx+i=x+1npi(2fi+gi)

化简系数为 1 1 1 ,得到最终转移式:
f x = 1 + 2 p x f x + ∑ i = x + 1 n p i ( 2 f i + g i ) 1 − p x f_x=\frac{1+2p_xf_x+\sum\limits^n_{i=x+1}p_i(2f_i+g_i)}{1-p_x} fx=1px1+2pxfx+i=x+1npi(2fi+gi)

答案:
a n s = ∑ i = 1 n p i ( 1 + 2 f i + g i ) ans=\sum^n_{i=1}p_i(1+2f_i+g_i) ans=i=1npi(1+2fi+gi)

提取分项概率化简:
a n s = 1 + ∑ i = 1 n p i ( 2 f i + g i ) ans=1+\sum^n_{i=1}p_i(2f_i+g_i) ans=1+i=1npi(2fi+gi)

一些注意事项

逆元请利用费马小定理和快速幂计算。

式子多处乘法操作,请注意及时取模,否则容易炸long long(个人写完之后添了好几次取模才成功过样例)

参考代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=998244353;
ll n,w[101],sum,p[101],f[101],g[101];
ll powmod(ll x,ll p){ll ret=1;while(p){if(p&1)ret=ret*x%mod;x=x*x%mod;p>>=1;}return ret;}//快速幂计算逆元
int main()
{
    std::ios::sync_with_stdio(false),cin.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){cin>>w[i];sum+=w[i];}//读入权值,计算总和
    sum=powmod(sum,mod-2);//将分母的权值和取逆元
    for(int i=1;i<=n;i++)p[i]=w[i]*sum%mod;//用逆元进行乘法计算,得出概率
    f[n]=powmod(1-p[n]+mod,mod-2);//优先算好f[n],注意该项是没有Σ的
    sum=p[n]*f[n]%mod;//sum存储后文中计算时Σ项
    for(int i=n-1;i>=1;i--){
        f[i]=(1+sum)*powmod(1-p[i]+mod,mod-2)%mod;//改除法为逆元乘法运算,不要忘记取模
        sum=(p[i]*f[i]%mod+sum)%mod;//更新Σ项,不要忘记取模
    }
    g[n]=(2*p[n]%mod*f[n]%mod+1)%mod*powmod(1-p[n]+mod,mod-2)%mod;//优先算好g[n],注意该项是没有Σ的
    sum=(g[n]+2*f[n])%mod*p[n]%mod;//sum存储后文中计算时Σ项
    for(int i=n-1;i>=1;i--){
        g[i]=(2*p[i]%mod*f[i]%mod+1+sum)%mod*powmod(1-p[i]+mod,mod-2)%mod;//改除法为逆元乘法运算,不要忘记取模
        sum=((g[i]+2*f[i])%mod*p[i]%mod+sum)%mod;//更新Σ项,不要忘记取模
    }
//  cout<<(sum+1)%mod<<endl;//其实此时sum已经存储了所有的情况结果,离ans只差了有关p的概率总和项,即差1
	ll ans=1;//ans在计算时首先赋值为概率总和,即式子中的1
    for(int i=1;i<=n;i++)ans=((g[i]+2*f[i])%mod*p[i]%mod+ans)%mod;//计算ans,不要忘记取模
    cout<<ans<<endl;
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值