Solution
对于
o
p
=
0
op=0
op=0,直接维护
f
i
,
j
f_{i,j}
fi,j表示第
i
i
i个人此时剩下
j
j
j点生命值的概率即可。
对于
o
p
=
1
op=1
op=1,需要知道每个人在存活的情况下存活
i
i
i个人的概率,这其实是可以DP的,用的是消失之物这道题的一个做法,设
s
j
s_j
sj为在
k
k
k个人中选
j
j
j个存活的概率和,
h
i
,
j
h_{i,j}
hi,j为令第
i
i
i个人必定死亡的情况下选出
j
j
j个存活的概率和,显然
h
i
,
0
=
s
0
h_{i,0}=s_0
hi,0=s0,然后这样递推
h
i
,
j
=
s
j
−
h
i
,
j
−
1
÷
f
i
,
0
×
(
∑
j
=
1
100
f
i
,
j
)
h_{i,j}=s_j-h_{i,j-1}\div f_{i,0}\times (\sum_{j=1}^{100}f_{i,j})
hi,j=sj−hi,j−1÷fi,0×(j=1∑100fi,j)
正确性显然。这个小技巧还是十分重要的,要好好记住。注意要特判一些
0
0
0的情况。
Code
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=210,Maxm=110;
const int inf=2147483647;
const int mod=998244353;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
void upd(int&x,int y){x+=y;if(x>=mod)x-=mod;}
int n,m,f[Maxn][Maxm],s[Maxn][Maxn],h[Maxn][Maxn],a[Maxn],b[Maxn],c[Maxn],inv[Maxn],invc[Maxn];
int Pow(int x,int y)
{
if(!y)return 1;
int t=Pow(x,y>>1),re=(LL)t*t%mod;
if(y&1)re=(LL)re*x%mod;
return re;
}
int main()
{
n=read();
inv[0]=inv[1]=1;for(int i=2;i<=n;i++)inv[i]=(LL)(mod-mod/i)*inv[mod%i]%mod;
for(int i=1;i<=n;i++)
for(int j=0;j<=101;j++)
f[i][j]=0;
for(int i=1;i<=n;i++)f[i][read()]=1;
int Q=read();
while(Q--)
{
int op=read(),k=read(),u,v;
if(!op)
{
u=read(),v=read();
int g=(LL)u*Pow(v,mod-2)%mod,gg=(1-g+mod)%mod;
for(int i=0;i<=100;i++)f[k][i]=(LL)f[k][i]*gg%mod,upd(f[k][i],(LL)f[k][i+1]*g%mod);
}
else
{
int cnt=0;
for(int i=1;i<=k;i++)
{
a[i]=read();
b[i]=0;
for(int j=1;j<=100;j++)upd(b[i],f[a[i]][j]);
c[i]=(1-b[i]+mod)%mod,invc[i]=Pow(c[i],mod-2);
if(!invc[i])cnt++;
}
s[0][1]=0;s[0][0]=1;
for(int i=1;i<=k;i++)
for(int j=0;j<=i;j++)
{
s[i][j]=(LL)s[i-1][j]*c[i]%mod;
if(j)upd(s[i][j],(LL)s[i-1][j-1]*b[i]%mod);
}
for(int i=1;i<=k;i++)
{
h[i][0]=s[k][0];
for(int j=1;j<=k;j++)
{
if(!invc[i])h[i][j]=0;
else h[i][j]=(s[k][j]-(LL)h[i][j-1]*invc[i]%mod*b[i]%mod+mod)%mod;
}
}
for(int i=1;i<=k;i++)
{
int ans=0;
for(int j=1;j<=k;j++)upd(ans,(LL)((s[k][j]-h[i][j]+mod)%mod)*inv[j]%mod);
printf("%d ",ans);
}
puts("");
}
}
for(int i=1;i<=n;i++)
{
int ans=0;
for(int j=1;j<=100;j++)upd(ans,(LL)f[i][j]*j%mod);
printf("%d ",(LL)ans);
}
}