zoukankan      html  css  js  c++  java
  • BZOJ5340: [Ctsc2018]假面

    BZOJ5340: [Ctsc2018]假面

    https://lydsy.com/JudgeOnline/problem.php?id=5340

    分析:

    • 背包,只需要求(g_{i,j})表示强制活第(i)个人一共活了(j)个人的概率,(f_j)表示活了(j)个人的概率 。
    • 这个东西有(g_{i,j}=f_{j}-g_{i,j+1} imes p_i/(1-p_i))
    • 转移即可,有小细节。
    • (p_i)可能为(0)使得没有逆元,不过此时答案一定为(0)
    • 在计算第(i)个人血量为(j)的概率时,(0)的转移比较特殊 。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    using namespace std;
    typedef long long ll;
    #define mod 998244353
    #define N 205
    #define MAXH 105
    int n,Q,id[N],inv[N];
    ll h[N],P[N][MAXH],old[MAXH],num[N],f[N][N],g[N][N];
    ll qp(ll x,ll y) {ll re=1;for(;y;y>>=1,x=x*x%mod)if(y&1)re=re*x%mod; return re;}
    ll INV(ll x) {return qp(x,mod-2);}
    int main() {
    	int i,op,j;
    	scanf("%d",&n);
    	for(i=1;i<=n;i++) inv[i]=INV(i);
    	for(i=1;i<=n;i++) scanf("%lld",&h[i]),P[i][h[i]]=1;
    	scanf("%d",&Q);
    	for(;Q--;) {
    		scanf("%d",&op);
    		if(op==0) {
    			int x,u,v;
    			scanf("%d%d%d",&x,&u,&v);
    			ll tmp=ll(u)*INV(v)%mod;
    			for(i=h[x]+1;i>=0;i--) old[i]=P[x][i];
    			for(i=h[x];i>=0;i--) {
    				if(i) P[x][i]=(old[i]*(1-tmp)+old[i+1]*tmp)%mod;
    				else P[x][i]=(P[x][i]+old[i+1]*tmp)%mod;
    			}
    		}else {
    			int k;
    			scanf("%d",&k);
    			for(i=1;i<=k;i++) scanf("%d",&id[i]);
    			for(i=1;i<=k;i++) num[i]=(mod+1-P[id[i]][0])%mod;
    			memset(f,0,sizeof(f));
    			memset(g,0,sizeof(g));
    			f[0][0]=1;
    			for(i=1;i<=k;i++) {
    				for(j=k;j>=0;j--) {
    					f[i][j]=f[i-1][j]*(1-num[i])%mod;
    					if(j) f[i][j]=(f[i][j]+f[i-1][j-1]*num[i])%mod;
    				}
    			}
    			for(i=1;i<=k;i++) {
    				if(!num[i]) {printf("0 "); continue;}
    				g[i][k]=f[k][k];
    				ll tmp=(1-num[i])*INV(num[i])%mod;
    				for(j=k-1;j>=1;j--) {
    					g[i][j]=(f[k][j]-g[i][j+1]*tmp)%mod;
    				}
    				ll re=0;
    				for(j=1;j<=k;j++) re=(re+g[i][j]*inv[j])%mod;
    				printf("%lld ",(re+mod)%mod);
    			}
    			puts("");
    		}
    	}
    	for(i=1;i<=n;i++) {
    		ll re=0;
    		for(j=1;j<=h[i];j++) re=(re+j*P[i][j])%mod;
    		printf("%lld ",(re+mod)%mod);
    	}
    	puts("");
    }
    
  • 相关阅读:
    51 Nod 1086 多重背包问题(单调队列优化)
    51 Nod 1086 多重背包问题(二进制优化)
    51 Nod 1085 01背包问题
    poj 2559 Largest Rectangle(单调栈)
    51 Nod 1089 最长回文子串(Manacher算法)
    51 Nod N的阶乘的长度 (斯特林近似)
    51 Nod 1134 最长递增子序列(经典问题回顾)
    51 Nod 1020 逆序排列
    PCA-主成分分析(Principal components analysis)
    Python中cPickle
  • 原文地址:https://www.cnblogs.com/suika/p/10264151.html
Copyright © 2011-2022 走看看