zoukankan      html  css  js  c++  java
  • loj#2552. 「CTSC2018」假面

    题目链接

    loj#2552. 「CTSC2018」假面

    题解

    本题严谨的证明了我菜的本质
    对于砍人的操作好做找龙哥就好了,blood很少,每次暴力维护一下
    对于操作1
    (a_i)为第i个人存活的概率,(d_i)为死掉的概率,(g_{i,j})是除i以外活了j个人的概率
    那个选中i人的答案就是

    [a_i imessum_{j = 0} ^{k - 1}frac{g_{i,j}}{j + 1} ]

    对于(g_{i,j}) ,设(f_{i,j})表示前(i)个人有(j)个活着的概率,(f_{i,j})可以dp出来

    [f_{i,j} = f_{i - 1,j} imes d_i + f_{i - 1,j - 1} imes a_i ]

    我们可以枚举每次(g_{i,j})的i,然后skip掉,这样的复杂度是(n^3)
    然后就可以前缀后缀背包卷积NTT,或者单点删除的分治做法hhhhhhh
    其实这个被背包删除物品可以做O(n)
    逆着推一下就好了

    代码

    
    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c < '0' || c > '9') c = getchar(); 
    	while(c <= '9' && c >= '0') x = x * 10 + c - '0' ,c = getchar(); 
    	return x * f; 
    } 
    const int mod = 998244353; 
    const int maxn = 2007; 
    long long b[maxn]; 
    int n,m ; 
    long long p[maxn][maxn]; 
    long long inv[maxn]; 
    inline int add(int x,int y) { 
    	return x + y >= mod ? x + y - mod : x + y; 
    } 
    inline int fstpow(int x,int k) { 
    	int ret = 1; 
    	for(;k;k >>= 1,x = 1ll *x * x % mod) 
    		if(k & 1) ret = 1ll * ret * x % mod; 
    	return ret;  
    } 
    void solve1(int x,int P) { 
    	int rp = 1 + mod - P; 
    	for(int i = 0;i <= b[x];++ i) { 
    		if(i) p[x][i] = 1ll * p[x][i] * rp % mod; 
    		if(i < b[x]) p[x][i] = add(p[x][i] , 1ll * p[x][i + 1] * P % mod) ;  
    	} 
    } 
    int k;
    void solve(int k) { 
    	static long long f[maxn],g[maxn],h[maxn],t[maxn]; 
    	// f存活j个人的概率  
    	memset(f,0,sizeof f); 
    	f[0] = 1; 
    	for(int i = 1;i <= k;++ i) t[i] = read(); 	
    	for(int a,d,i = 1;i <= k;++ i) { 
    		a = 1 + mod - p[t[i]][0];
    		d = p[t[i]][0];  
    		for(int j = i;j >= 0;-- j) 
    			f[j] = add((j ? 1ll * f[j - 1] * a % mod : 0) , 1ll * f[j] * d % mod);
    	} 
    	for(int i = 1;i <= k;++ i) { 
    		h[i] = 0; 
    		int a = 1 + mod - p[t[i]][0]; 
    		if(!p[t[i]][0]) 
    			for(int j = 0;j < k;++ j) h[i] = add(h[i],1ll * f[j + 1] * inv[j + 1] % mod); 
    		else { 
    			int Inv = fstpow(p[t[i]][0],mod - 2); 
    			for(int j = 0;j < k;++ j) { 
    				g[j] = ((f[j] - (j ? 1ll * g[j - 1] * a % mod : 0) + mod) % mod) * Inv % mod; 
    				h[i] = add(h[i],1ll * g[j] * inv[j + 1] % mod); 
    			} 
    		} 
    		h[i] = 1ll * h[i] * a % mod; 
    	} 
    	for(int i = 1;i <= k;++ i) printf("%d ",h[i]); 	
    	puts(""); 
    } 
    main() { 
    	//freopen("facel5.in","r",stdin); freopen("w.out","w",stdout); 
    	n = read(); 
    	for(int i = 1;i <= n;++ i) b[i] = read(), p[i][b[i]] = 1,inv[i] = fstpow(i,mod - 2);
    	m = read(); 
    	for(int op,i = 1;i <= m;i += 1) { 
    		op = read(); 
    		if(!op) { 
    			int x = read(),u = read(),v = read(); 
    			solve1(x,1ll * u * fstpow(v,mod - 2) % mod); 
    		} 
    		else 
    			solve(read());  
    	}	
     
    	for(int i = 1;i <= n;++ i) { 
    		int sum = 0; 
    		for(int j = 1;j <= b[i];++ j) 
    			sum = add(sum , 1ll * j * p[i][j] % mod) ; 
    		printf("%d%c",sum,i != n ? ' ' : '
    '); 
    	} 
    	return 0; 
    } 
    
  • 相关阅读:
    安装lnmp 时如何修改数据库数据存储地址及默认访问地址
    ubuntu 设置root用户密码并实现root用户登录
    解决ubuntu 远程连接问题
    linux 搭建FTP服务器
    PHP 根据ip获取对应的实际地址
    如何发布自己的composer包
    使用composer安装composer包报Your requirements could not be resolved to an installable set of packages
    laravel 框架配置404等异常页面
    使用Xshell登录linux服务器报WARNING! The remote SSH server rejected X11 forwarding request
    IoTSharp 已支持国产松果时序数据库PinusDB
  • 原文地址:https://www.cnblogs.com/sssy/p/9581007.html
Copyright © 2011-2022 走看看