zoukankan      html  css  js  c++  java
  • [CTSC2018]假面

    题目大意:

      有(n(n≤200))个人,每个人初始血量为(m_i(mi≤100))对这些人进行(q(q≤2×10^5))次操作,操作包含以下两种:
      1. 选择编号为idid的人,有pp的概率扣掉一滴血;
      2. 编号为(id1,id2,…,idk)的k个人,等概率的从这k个人中选取一个活着的人封印,问这k个人中每个人被封印的概率是多少。
      处理完所有操作后,求每个人最终血量的期望。

    题解

    n,m都很小,所以第一问肥肠简单

    (f[i][j])表示第(i)个人有(j)滴血的概率然后直接背包就好了

    注意当j=0时不要从这一层转移,只从上一层转移,因为如果已经死了就不会被打到了

    然后第二问怎么求?

    (g[i][j])表示选择一个人u后前i个人剩j个的概率

    (g[i][j] = g[i-1][j-1]*liv[u] + g[i-1][j]*die[u])

    然后再对选择的这个人求答案(Ans = sum_{i = 0}^{i<=k}{frac{g[k-1][i] * liv[u]}{i+1}})

    这样就是(O(Cn^3))

    然后考虑优化

    显然(g[][])可以去掉第一维

    可以发现(g[])似乎可以倒着推?

    (g_{last}[j] = (g[j] - g_{last}[j-1] * liv[i]) / die[i])

    所以可以(O(k^2))先预处理出g[]

    然后倒着推出(g_{last})

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    # define LL long long
    const int M = 205 ;
    const LL mod = 998244353 ;
    using namespace std ;
    inline LL read() {
    	char c = getchar() ; LL x = 0 , w = 1 ;
    	while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
    	while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
    	return x*w ;
    }
    
    int n , Num , peo[M] ;
    LL hp[M] , f[M][M] , inv[M] ;
    LL liv[M] , die[M] , t[M] , g[M] ;
    
    void Exgcd(LL a , LL b , LL &x , LL &y) {
    	if(b == 0) {
    		x = 1 ; y = 0 ;
    		return ;
    	}
    	Exgcd(b , a % b , x , y) ;
    	LL tmp = x ; 
    	x = y ; 
    	y = tmp - a / b * y ;
    }
    
    inline LL Inv(LL a) {
    	LL x , y ;
    	Exgcd(a , mod , x , y) ;
    	return (x + mod) % mod ;
    }
    // g[i] 表示有i个人存活的概率 
    inline void Solve() {
    	Num = read() ;
    	for(int i = 1 ; i <= Num ; i ++) {
    		peo[i] = read() ;
    		die[i] = f[peo[i]][0] ;
    		liv[i] = (1 - die[i] + mod) % mod ;
    	}
    	memset(g , 0 , sizeof(g)) ;
    	g[0] = 1 ;
    	for(int i = 1 ; i <= Num ; i ++)
    	    for(int j = i ; j >= 0 ; j --) {
    	        g[j] = (g[j] * die[i]) % mod ;
    	        if(j > 0) g[j] = (g[j] + g[j - 1] * liv[i] + mod) % mod ;
    		}
    	LL Ans = 0 , x ;
    	for(int i = 1 ; i <= Num ; i ++) {
    		Ans = 0 ; x = Inv(die[i]) ;
    		if(die[i]) {
    			t[0] = (g[0] * x) % mod ;
    			for(int j = 1 ; j < Num ; j ++)
    			    t[j] = ((g[j] - (t[j - 1] * liv[i]) % mod + mod) % mod * x) % mod ;
    		}
    		else for(int j = 0 ; j < Num ; j ++) t[j] = g[j + 1] ;
    		for(int j = 0 ; j < Num ; j ++) 
    			Ans = (Ans + t[j] * ((liv[i] * inv[j + 1]) % mod) % mod + mod) % mod ;
    		printf("%lld ",Ans) ;
    	}
    	printf("
    ") ;
    }
    int main() {
    	n = read() ; inv[1] = 1 ; 
    	for(int i = 2 ; i <= n + 1 ; i ++) inv[i] = Inv(i) ;
    	for(int i = 1 ; i <= n ; i ++) {
    		hp[i] = read() ;
    	    f[i][hp[i]] = 1 ;
    	}
    	int Q = read() ;
    	LL opt , x , u , v , p ;
    	while(Q --) {
    		opt = read() ;
    		if(opt == 0) {
    			x = read() ; u = read() , v = read() ;
    			p = (u * Inv(v)) % mod ;
    			for(int j = 0 ; j <= hp[x] ; j ++) {
    				if(j) f[x][j] = (f[x][j] * (1 - p + mod)) % mod ;
    				if(j < hp[x]) f[x][j] = (f[x][j] + f[x][j + 1] * p + mod) % mod ;
    			}
    		}
    		else Solve() ;
    	}
    	LL Ans = 0 ;
    	for(int i = 1 ; i <= n ; i ++) {
    		Ans = 0 ;
    		for(int j = 1 ; j <= hp[i] ; j ++)
    		    Ans = (Ans + f[i][j] * j) % mod ;
    		printf("%lld ",Ans) ;
    	}
    	printf("
    ") ;
    	return 0 ;
    }
    
  • 相关阅读:
    JMeter——请求元件——配置元件——参数化——用户自定义变量
    JMeter——结合fiddler查看响应结果
    JMeter——断言——xpath Assertion
    JMeter——断言——响应断言
    JMeter——配置元件——http信息头管理器使用
    JMeter——查看结果树——html使用
    JMeter——查看结果树 ——css_jquery_tester(css选择器测试)
    JMeter——查看结果树
    JMeter——http请求默认值
    java.lang.RuntimeException: Cannot reconnect.
  • 原文地址:https://www.cnblogs.com/beretty/p/10033362.html
Copyright © 2011-2022 走看看