[bzoj5340]假面
全部存概率,第一问直接更新,第二问存 i 个人存活的概率,这个可以用多项式除二项式优化到 n^2
然后复杂度就对了。
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=205;
int m[N],n;
const int mod=998244353;
int g[N][N];
inline int add(int a,int b) {
a+=b;
if(a>=mod)a-=mod;
return a;
}
inline int mul(int a,int b) {
a=(ll)a*b%mod;
return a;
}
inline int sub(int a,int b) {
a-=b;
if(a<0)a+=mod;
return a;
}
int INVV[N];
int qpow(int a,int b) {
int res=1;
while(b) {
if(b&1)res=(ll)res*a%mod;
b>>=1,a=(ll)a*a%mod;
}
return res;
}
int inv(int x) {
return qpow(x,mod-2);
}
inline void init() {
for(int i=1; i<N; i++)INVV[i]=inv(i);
}
/**&**&**&**/
int psblive(int id) {
return sub(1,g[id][0]);
}
int psbdead(int id) {
return g[id][0];
}
int id[N];
int T[N],T2[N];
int f[N];
int main() {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d",&m[i]);
g[i][m[i]]=1;
}
int Q;
scanf("%d",&Q);
init();
while(Q--) {
int opt;
scanf("%d",&opt);
if(opt==0) {
int id,u,v;
scanf("%d%d%d",&id,&u,&v);
int psb1=mul(u,inv(v)), psb2=sub(1,psb1);
g[id][0]=add(g[id][0],mul(g[id][1],psb1));
for(int i=1; i<=m[id]; i++) {
g[id][i]=add(mul(g[id][i+1],psb1),mul(g[id][i],psb2));
}
} else {
int k;
scanf("%d",&k);
for(int i=1; i<=k; i++)scanf("%d",&id[i]);
for(int i=0; i<=k; i++) T[i]=0;
T[0]=1;
for(int i=1; i<=k; i++) {
int pos1=psblive(id[i]),pos2=psbdead(id[i]);
for(int j=k; j; j--)
T[j]=add(mul(T[j],pos2),mul(T[j-1],pos1));
T[0]=mul(T[0],pos2);
}
for(int i=1; i<=k; i++) {
int pos1=psblive(id[i]),pos0=psbdead(id[i]);
int inv1=inv(pos1);
f[k]=0;
for(int t=k-1; ~t; t--)
f[t]=mul(sub(T[t+1],mul(f[t+1],pos0)),inv1);
int pos11=0;
for(int t=0; t<=k-1; t++)
pos11=add(pos11,mul(f[t],INVV[t+1]));
pos11=mul(pos11,pos1);
printf("%d ",pos11);
}
puts("");
}
}
int ans=0;
for(int i=1; i<=n; i++) {
ans=0;
for(int j=1; j<=m[i]; j++)
ans=add(ans,mul(j,g[i][j]));
printf("%d ",ans);
}
puts("");
}