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(1≤n≤100) 之间的随机数的生成器,生成
x
(
1
≤
x
≤
n
)
x(1\le x\le n)
x(1≤x≤n) 的概率为
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(1≤i≤n) ,
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=1∑x−1pi ;
②
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+1∑npi(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=1∑x−1pi+px(1+fx)+i=x+1∑npi(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)
(1−px)fx=i=1∑x−1pi+px+i=x+1∑npi(1+fi)
发现右侧包含所有
p
i
(
1
≤
i
≤
n
)
p_i(1\le i\le n)
pi(1≤i≤n) (即全部分项概率,总和为
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
(1−px)fx=1+i=x+1∑npifi
化简系数为
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=1−px1+i=x+1∑npifi
然后我们考虑构造转化
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=1∑x−1pi ;
②
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+1∑npi(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+1∑npi(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=1∑x−1pi+px(1+2fx+gx)+i=x+1∑npi(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)
(1−px)gx=i=1∑x−1pi+px+2pxfx+i=x+1∑npi(1+2fi+gi)
发现右侧包含所有
p
i
(
1
≤
i
≤
n
)
p_i(1\le i\le n)
pi(1≤i≤n) (即全部分项概率,总和为
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)
(1−px)fx=1+2pxfx+i=x+1∑npi(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=1−px1+2pxfx+i=x+1∑npi(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=1∑npi(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=1∑npi(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;
}