zoukankan      html  css  js  c++  java
  • 【ZJOI2020】传统艺能【矩阵快速幂】【DP】

    Description

    给定一棵 ([1,n]) 范围内的广义线段树,(k) 次等概率随机选择一个区间 ([l,r]) 执行区间覆盖操作,问最终 (tag=1) 的节点数量的期望。

    (nle 200000,kle 10^9)

    Solution

    根据期望的线性性,可以先求出每个节点最终 (tag=1) 的概率,加起来即为答案。

    考虑每一个区间覆盖对当前节点 (tag) 的影响,因为祖先节点可能会下传 (tag),因此也要考虑祖先节点的状态。可以将状态分为:

    • 当前节点和祖先都没有标记
    • 祖先节点有标记,当前节点没有标记
    • 当前节点有标记

    (3) 种状态。

    不妨设父亲节点 (f) 的区间为 ([L,R]),当前节点 (p) 的区间为 ([l,r]),询问区间为 ([ql,qr])

    • 修改与 ([L,R]) 无交,即 (1le qlle qr<L)(R<qlle qrle n):此时对状态无影响。

    • 修改包含 (f),并在某个 (u) 的祖先处打标记终止,即 (qlin [1,L],qrin [R,n]),此时会导致祖先节点带上标记。

    • 修改包含 (u),在 (u) 上打标记终止,此时 (qlin [1,l],qrin [r,n]) 且不属于上一种情况。此时会导致自己带上标记,并且会让祖先节点的标记全部下传。

    • 修改进入了 (f),但下一步只进入 (f) 的另一个儿子而不进入 (u),即 (1le qlle Lle qr< l) ,或 (r<qlle Rle rle n):此时祖先节点的标记会下传。

    • 修改与 (u) 相交,进入 (u) 后继续向下递归:此时祖先节点与当前节点的标记都会清零。

    分类讨论这 (5) 种情况,设 (f_{i,0/1/2}) 表示考虑了前 (i) 次修改,当前状态为 (0/1/2) 的概率,不难列出转移方程,然后矩阵快速幂优化即可做到 (mathcal O(3^3nlog k)).

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=4e5+10,mod=998244353;
    int n,k,m[N],tot,L[N],R[N],fa[N],p[N],q[N],g[N],r[N];
    inline void dfs(int l,int r,int f){
    	int p=++tot;L[p]=l;R[p]=r;fa[p]=f;
    	if(L[p]!=R[p]){
    		scanf("%d",&m[p]);
    		dfs(l,m[p],p);dfs(m[p]+1,r,p);
    	}
    }
    inline int add(int x,int y){return (x+y>=mod)?x+y-mod:x+y;}
    inline int dec(int x,int y){return (x-y<0)?x-y+mod:x-y;}
    inline int ksm(int x,int y){
    	int ret=1;
    	for(;y;y>>=1,x=1ll*x*x%mod) if(y&1) ret=1ll*ret*x%mod;
    	return ret;
    } 
    struct matrix{
    	int c[3][3];
    	inline void init(int d){
    		for(int i=0;i<3;++i) for(int j=0;j<3;++j) c[i][j]=i==j?d:0;
    	}
    	inline matrix operator *(const matrix &A){
    		matrix ret;
    		for(int i=0;i<3;++i){
    			for(int j=0;j<3;++j){
    				ll tmp=0;
    				for(int k=0;k<3;++k) tmp+=1ll*c[i][k]*A.c[k][j];
    				ret.c[i][j]=tmp%mod;
    			}
    		}
    		return ret;
    	}
    	inline matrix operator ^(int k){
    		matrix ret,A=*this;ret.init(1);
    		for(;k;k>>=1,A=A*A) if(k&1) ret=ret*A;
    		return ret;
    	}
    };
    inline int S(int x){return (1ll*x*(x+1)/2)%mod;}
    int main(){
    	scanf("%d%d",&n,&k);
    	dfs(1,n,0);
    	int al=S(n),all=ksm(S(n),mod-2),ans=0;
    	for(int i=1;i<=tot;++i){
    		int l=L[i],r=R[i],fl=L[fa[i]],fr=R[fa[i]];
    		int p1=add(S(fl-1),S(n-fr));//与父亲无交 
    		int p2=1ll*fl*(n-fr+1)%mod;//标记祖先 
    		int p3=dec(1ll*l*(n-r+1)%mod,p2);//标记自己
    		int p4=add(dec(S(l-1),S(fl-1)),dec(S(n-r),S(n-fr)));//下传父亲,不进入自己 
    		int p5=dec(al,add(add(p1,p2),add(p3,p4)));//与自己交但不包含 
    		matrix A;A.init(0);
    		A.c[0][0]=1ll*add(p1,add(p4,p5))*all%mod;A.c[0][1]=1ll*p5*all%mod;A.c[0][2]=1ll*p5*all%mod;
    		A.c[1][0]=1ll*p2*all%mod;A.c[1][1]=1ll*add(p1,p2)*all%mod;
    		A.c[2][0]=1ll*p3*all%mod;A.c[2][1]=1ll*add(p3,p4)*all%mod;A.c[2][2]=1ll*dec(al,p5)*all%mod;
    		A=A^k;
    		ans=add(ans,A.c[2][0]);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    isEmpty和isBlank区别
    java加密算法相关
    页面跳转、替换、刷新
    打开一个网站都经过了什么
    css3动画和JS+DOM动画和JS+canvas动画比较
    canvas如何兼容IE8
    移动端的300毫秒延迟问题
    几道前端的面试题
    js执行过程
    微信查看网页源代码的方法
  • 原文地址:https://www.cnblogs.com/tqxboomzero/p/14883244.html
Copyright © 2011-2022 走看看