P4564-[CTSC2018]假面【期望dp】
正題
題目大意:https://www.luogu.com.cn/problem/P4564
題目大意
n n n個人第 i i i個有 m i m_i mi點血,每次有操作
- 有 p p p的概率對一個人造成 1 1 1點傷害(如果死了就不算, p p p每次都不同)
- 給出若干個人,對裡面存活的人隨機選擇一個,求每個人被選中的概率
最後要求輸出每個人的期望血量
解題思路
p i , j p_{i,j} pi,j表示第 i i i個人剩餘 j j j點血的概率。這個可以 O ( Q n ) O(Qn) O(Qn)的時間內維護。
考慮如何計算概率,因為存活人數的不同,產生的貢獻也不同,我們設 f i , j f_{i,j} fi,j表示第 i i i個人以外的人存活了 j j j個的概率,這個很容易可以在 O ( C n 2 ) O(Cn^2) O(Cn2)的時間內算,但是這樣顯然過不去。
所以我們要進行優化,我們可以在
O
(
n
2
)
O(n^2)
O(n2)的時間內算出
g
i
g_i
gi表示所有人裡存活
i
i
i個人的概率,也就是有(以下為了方便定義
p
i
p_i
pi表示
1
−
p
i
,
0
1-p_{i,0}
1−pi,0即第
i
i
i個人存活的概率):
g
i
=
g
i
−
1
∗
p
u
+
g
i
∗
(
1
−
p
u
)
g_i=g_{i-1}*p_u+g_{i}*(1-p_u)
gi=gi−1∗pu+gi∗(1−pu)
顯然我們可以從
f
u
f_{u}
fu推到
g
g
g
g
i
=
f
u
,
i
∗
(
1
−
p
u
)
+
f
u
,
i
−
1
∗
p
u
g_i=f_{u,i}*(1-p_u)+f_{u,i-1}*p_u
gi=fu,i∗(1−pu)+fu,i−1∗pu可以回推回來也就是
⇒
f
u
,
i
=
g
i
−
f
u
,
i
−
1
∗
p
u
1
−
p
u
\Rightarrow f_{u,i}=\frac{g_i-f_{u,i-1}*p_u}{1-p_u}
⇒fu,i=1−pugi−fu,i−1∗pu
這樣我們就可以在 O ( C n 2 ) O(Cn^2) O(Cn2)的時間內算出所有的 f u , i f_{u,i} fu,i來統計答案。因為求逆元也很慢,所以我們先線性推逆元預處理一下比較小的值。
c o d e code code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
const int XJQ=998244353;
int n,Q,p[210][210],c[210],g[210],f[210],in[210];
int power(int x,int b){
int ans=1;x%=XJQ;
while(b){
if(b&1)ans=1ll*ans*x%XJQ;
x=1ll*x*x%XJQ;b>>=1;
}
return ans;
}
int read() {
int x=0,f=1; char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
return x*f;
}
void print(int x){
if (x>9) print(x/10); putchar(x%10+48); return;
}
signed main()
{
n=read();
for(int i=1;i<=n;i++)p[i][read()]=1;
Q=read();in[1]=1;
for(int i=2;i<=n;i++)
in[i]=(long long)XJQ-(long long)XJQ/i*in[XJQ%i]%XJQ;
while(Q--){
int op=read();
if(op==0){
int id=read(),u=read(),v=read();
u=1ll*u*power(v,XJQ-2)%XJQ;
p[id][0]=(p[id][0]+1ll*p[id][1]*u)%XJQ;
for(int i=1;i<=100;i++)
p[id][i]=(1ll*p[id][i+1]*u+1ll*p[id][i]*(1-u+XJQ))%XJQ;
}
else{
int k=read(),x,ans=0;
for(int i=1;i<=k;i++)c[i]=read();
memset(g,0,sizeof(g));g[0]=1;
for(int i=1;i<=k;i++){
for(int j=i;j>=1;j--)
g[j]=(1ll*g[j]*p[c[i]][0]+1ll*(1-p[c[i]][0]+XJQ)*g[j-1])%XJQ;
g[0]=1ll*g[0]*p[c[i]][0]%XJQ;
}
for(int i=1;i<=k;i++){
int ans=0,z=(1-p[c[i]][0]+XJQ)%XJQ,inv=power(p[c[i]][0],XJQ-2);
if(p[c[i]][0]==1){
printf("0 ");
continue;
}
if(p[c[i]][0]==0)
for(int j=0;j<k;j++)
f[j]=g[j+1];
else{
f[0]=1ll*g[0]*inv%XJQ;
for(int j=1;j<k;j++){
f[j]=(g[j]-1ll*f[j-1]*z%XJQ+XJQ)%XJQ;
f[j]=1ll*f[j]*inv%XJQ;
}
}
for(int j=0;j<k;j++)
(ans+=1ll*f[j]*in[j+1]%XJQ)%=XJQ;
print(1ll*ans*z%XJQ);putchar(' ');
}
putchar('\n');
}
}
for(int i=1;i<=n;i++){
int ans=0;
for(int j=1;j<=100;j++)
ans=(ans+1ll*p[i][j]*j%XJQ)%XJQ;
print(ans);putchar(' ');
}
}
相關文章
- LOJ#2552. 「CTSC2018」假面(期望 揹包)
- 費馬小定理-期望dp
- luogu P6835 概率DP 期望
- HDU4652 Dice(期望dp推式子)
- HNOI2015亞瑟王(期望dp)
- cf1097D. Makoto and a Blackboard(期望dp)
- 假面
- ZROJ#398. 【18提高7】隨機遊走(期望dp 樹形dp)隨機
- 【演算法學習筆記】概率與期望DP演算法筆記
- 洛谷P4550 收集郵票 題解 期望DP
- 動態規劃之經典數學期望和概率DP動態規劃
- [期望DP][紀中]【2010集訓隊出題】彩色圓環
- 洛谷P8208 [THUPC2022 初賽] 骰子旅行 題解 期望DP
- 洛谷P3600 隨機數生成器(期望dp 組合數)隨機
- 洛谷P1291 [SHOI2002]百事世界盃之旅(期望DP)
- 期望
- 洛谷 P4284 [SHOI2014]概率充電器 概率與期望+換根DP
- 牛客周賽 Round50 E-小紅的樹上移動 (期望dp+逆元)
- dp 套 dp(dp of dp)小記
- 機率期望
- DP套DP
- 20240710機率期望
- 【筆記】Tricks - 期望筆記
- [DP] 數位DP
- 【DP】Educational DP Contest
- dp套dp 隨寫
- Note - 機率與期望
- 機率期望訓練
- 組合機率期望
- 【DP】區間DP入門
- dp
- [DP] DP最佳化總結
- 對AyuWorld的期望 [The Expectation of AyuWorld]
- 序列 DP
- dp板子
- DP(一)
- six[Dp]
- 概率與期望習題總結