这签到题送我见祖宗了啊qaq
全世界都A了这题,像我这样只拿了10分的傻子怕是不多了吧。
我们考虑怎么求最后的期望生命值。
因为减到0血就不减了,所以我们不能直接每次期望算,只好考虑一个背包转移。
dp[i][j]表示i减了j滴血的概率。减了K[i]滴血就代表i死了。
每次攻击时对x做一个O(mi)的背包转移即可。
最后对每个人枚举减j滴血的情况计算即可。
我们考虑“结界”询问。
即就是问活着k个人的概率是多少。
对于一个人x,他的答案就是
∑k=0m−1f[k]∗p(x)∗1k+1
∑
k
=
0
m
−
1
f
[
k
]
∗
p
(
x
)
∗
1
k
+
1
其中f[k]表示除了x之外的那些人中活k个人的概率。p(x)表示x存活的概率。
这样我们对每个人都背包一遍。复杂度
O(Cn3+Qm)
O
(
C
n
3
+
Q
m
)
理论上只能通过70%的数据。
我们考虑怎么优化,背包转移其实是可逆的。
我们考虑背包的转移方程:
f′[i]=f[i−1]∗(1−p)+f[i]∗p
f
′
[
i
]
=
f
[
i
−
1
]
∗
(
1
−
p
)
+
f
[
i
]
∗
p
那么我们就有
f[i]=f′[i]−f[i−1]∗(1−p)p
f
[
i
]
=
f
′
[
i
]
−
f
[
i
−
1
]
∗
(
1
−
p
)
p
因此我们先n个全背包一遍。
然后每次处理一个人x时把它拿掉,得到不含他的背包即可。
注意处理p=0的情况。
复杂度
O(Cn2+Qm)
O
(
C
n
2
+
Q
m
)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 210
#define mod 998244353
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,dp[N][110],K[N],a[N],f[N],inv[N];//dp[i][j],i这个人目前减了j滴血的概率
inline int ksm(int x,int k){
int res=1;for(;k;k>>=1,x=(ll)x*x%mod) if(k&1) res=(ll)res*x%mod;return res;
}
inline void inc(int &x,int y){x+=y;x%=mod;}
int main(){
// freopen("a.in","r",stdin);
n=read();inv[1]=1;
for(int i=2;i<=n;++i) inv[i]=(ll)inv[mod%i]*(mod-mod/i)%mod;
for(int i=1;i<=n;++i) K[i]=read(),dp[i][0]=1;
int owo=read();
while(owo--){
int op=read();
if(!op){
int x=read(),y=read();y=(ll)y*ksm(read(),mod-2)%mod;
for(int i=K[x]-1;i>=0;--i) inc(dp[x][i+1],(ll)dp[x][i]*y%mod),dp[x][i]=(ll)dp[x][i]*(1-y+mod)%mod;
}else{
int m=read();for(int i=1;i<=m;++i) a[i]=read();memset(f,0,sizeof(f));f[0]=1;
for(int i=1;i<=m;++i){
int y=dp[a[i]][K[a[i]]];
for(int j=i-1;j>=0;--j) inc(f[j+1],(ll)f[j]*(1-y+mod)%mod),f[j]=(ll)f[j]*y%mod;
}for(int i=1;i<=m;++i){
int y=dp[a[i]][K[a[i]]],lst=1,res=0,invy=ksm(y,mod-2);
for(int j=1;j<=m;++j) if(j!=i) lst=(ll)lst*dp[a[j]][K[a[j]]]%mod;
for(int j=0;j<m;++j){
inc(res,(ll)(1-y+mod)*lst%mod*inv[j+1]%mod);
lst=y?(f[j+1]-(ll)lst*(1-y+mod)%mod)*invy%mod:f[j+2];lst%=mod;if(lst<0) lst+=mod;
}printf("%d ",res);
}puts("");
}
}for(int i=1;i<=n;++i){
int res=K[i];
for(int j=0;j<=K[i];++j) inc(res,-(ll)j*dp[i][j]%mod);if(res<0) res+=mod;
printf("%d ",res);
}return 0;
}