题目
有(n)个敌方单位,初始生命值分别为(m_1,cdots,m_n) ;
假面可以释放(Q)个技能:
$op = 0 , id , u , v $ 表示对(id)号敌人有(frac{u}{v})的概率造成(1)点伤害;
$op = 1 , k , a_1,cdots a_k $ 表示在这些位置中生命值为正的位置里随机选择一个位置释放结界;
你需要对每个(op=1),输出(a_1,cdots, a_k)中结界的期望((op=1)操作最多(C)次);
$n le 200 , Q le 200000 , C le 1000 ,m_i le 100 $ ;
题解
-
Part 1
-
设(f_{i,j})表示(i)受到的伤害为(j)的概率,设(x=frac{u}{v}),则(f_{i,j} = x imes f_{i,j-1} + (1-x) imes f_{i,j})
-
(p_i)表示(i)号敌人存活的概率,$p_i = sum_{j=0}^{m_i-1} f_{i,j} $
-
剩余生命的期望(q_i = sum_{j=0}^{m_i-1}f_{i,j} imes (m_i-j))
-
**Part 2 **
-
把所有(a_i)拎出来讨论,设存活概率为(p_i) , (g_{i,j})表示不算第(i)个敌人,存活的个数为(j)的概率,(G_j)表示所有人都算上存活个数为(j)的概率,一个人对于(G)的贡献是:
$G_{j} = p_i imes G_{j-1} + (1-p_i) imes G_{j} $
-
这个式子是可逆的,即:
[egin{cases} g_{i,j} &= frac{G_j - p_i imes g_{i,j-1}}{1-p_i} & p_i != 1 \ g_{i,j} &= G_{j+1} & p_i==1 end{cases} ] -
时间复杂度:(O(QM + nMC))
#include<bits/stdc++.h> #define vec vector<int> #define pb push_back #define mod 998244353 #define ll long long using namespace std; const int N=810; int n,m,a[N],b[N],f[N][N],tot,ny[N],p[N],g[N],t[N]; char gc(){ static char*p1,*p2,s[1000000]; if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); return(p1==p2)?EOF:*p1++; } int rd(){ int x=0;char c=gc(); while(c<'0'||c>'9')c=gc(); while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc(); return x; } int pw(int x,int y){ int re=1; if(y<0)y+=mod-1; while(y){ if(y&1)re=(ll)re*x%mod; y>>=1;x=(ll)x*x%mod; } return re; } void inc(int&x,int y){x+=y;if(x>=mod)x-=mod;} void solve(){ for(int i=1;i<=tot;++i)g[i]=0;g[0]=1; for(int i=1;i<=tot;++i){ int x=b[i],y=(mod+1-x)%mod; for(int j=tot;~j;--j){ g[j]=(ll)g[j]*y%mod; if(j)inc(g[j],(ll)g[j-1]*x%mod); } } for(int j=0;j<=tot;++j)t[j]=g[j]; for(int i=1;i<=tot;++i){ int re=0,x=b[i],y=pw((mod+1-x)%mod,mod-2); if(x==1){for(int j=0;j<tot;++j)g[j]=g[j+1];g[tot]=0;} else{ g[0]=(ll)g[0]*y%mod; for(int j=1;j<=tot;++j)g[j]=(g[j]-(ll)g[j-1]*x%mod+mod)%mod*y%mod; } for(int j=0;j<=tot;++j){ inc(re,(ll)ny[j+1]*b[i]%mod*g[j]%mod); g[j]=t[j]; } printf("%d ",re); } puts(""); } int main(){ // freopen("faceless.in","r",stdin); // freopen("faceless.out","w",stdout); n=rd(); for(int i=1;i<=n;++i)a[i]=rd(),f[i][0]=p[i]=1; ny[1]=1;for(int i=2;i<=n<<2;++i)ny[i]=1ll*(mod-mod/i)*ny[mod%i]%mod; m=rd(); for(int i=1;i<=m;++i){ int op,id,x,y; op=rd(); if(!op){ id=rd();x=rd();y=rd(); x=(ll)x*pw(y,mod-2)%mod; y=(mod+1-x)%mod;p[id]=0; for(int j=a[id]-1;~j;--j){ f[id][j]=(ll)f[id][j]*y%mod; if(j)inc(f[id][j],(ll)f[id][j-1]*x%mod); inc(p[id],f[id][j]); } }else { tot=rd(); for(int j=1;j<=tot;++j)b[j]=p[rd()]; solve(); } } for(int i=1;i<=n;++i){ int x=0; for(int j=0;j<a[i];++j)inc(x,(ll)(a[i]-j)*f[i][j]%mod); printf("%d ",x); } return 0; }