• 联考20200729 T3 树上的鼠



    分析:
    首先我们从博弈入手,看看什么情况先手必胜
    先考虑一条链的情况,假设链长为偶数,即存在中点,先手就可以抢占中点,后手无论怎么走,先手都可以走到其关于中点的对称点上
    最后后手无法操作,先手必胜
    当链长为奇数时,先手两个中点随便抢一个就可以胜利
    换在树上,求出直径中点,非直径上的点可以转化为直径上的,效果等价
    那么先手必败当且仅当起点为连通块直径的唯一中点
    转化一下问题,即一个连通块使得1不是直径唯一中点,即1的儿子的最深深度仅有一个
    考虑DP,\(f_{u,i}\)表示\(u\)为根,深度至多为\(i\)的连通块方案数
    这个暴力\(O(n^2)\)DP,发现只与最深深度有关,直接长链剖分优化就好了
    统计答案时强行钦定某个儿子最深深度为\(D\),其余的不超过\(D\)就好了,维护一个前缀和
    复杂度\(O(n)\)

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<vector>
    #include<string>
    
    #define maxn 2000005 
    #define MOD 998244353
    
    using namespace std;
    
    inline long long getint()
    {
    	long long num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n;
    vector<int>G[maxn];
    int cur,pos[maxn],son[maxn],dpt[maxn],mxd[maxn];
    long long f[maxn],g[maxn],h[maxn],sum[maxn],pd[maxn];
    int tmp[maxn];
    
    inline void dfs1(int u,int fa)
    {
    	dpt[u]=dpt[fa]+1,mxd[u]=dpt[u],g[u]=1;
    	for(int i=0;i<G[u].size();i++)if(G[u][i]!=fa)
    	{
    		dfs1(G[u][i],u),mxd[u]=max(mxd[u],mxd[G[u][i]]);
    		if(mxd[G[u][i]]>mxd[son[u]])son[u]=G[u][i];
    		g[u]=g[u]*(g[G[u][i]]+1)%MOD;
    	}
    }
    inline void dfs2(int u,int fa)
    {
    	pos[u]=++cur;if(son[u])dfs2(son[u],u);
    	for(int i=0;i<G[u].size();i++)if(G[u][i]!=fa&&G[u][i]!=son[u])dfs2(G[u][i],u);
    }
    
    inline void down(int u,int lim)
    {
    	if(h[u]!=1)
    	{
    		f[u]=f[u]*h[u]%MOD;
    		if(u<lim)h[u+1]=h[u+1]*h[u]%MOD;
    		h[u]=1;
    	}
    }
    
    inline void solve(int u,int p)
    {
    	f[pos[u]]=h[pos[u]]=sum[pos[u]]=1;
    	if(son[u])solve(son[u],u);
    	for(int i=0;i<G[u].size();i++)if(G[u][i]!=p&&G[u][i]!=son[u])
    	{
    		int v=G[u][i];solve(v,u);
    		for(int j=0;j<=mxd[v]-dpt[v];j++)
    		{
    			int k=j+1;
    			down(pos[v]+j,pos[v]+mxd[v]-dpt[v]),sum[pos[v]+j]=((j>0)*sum[pos[v]+j-1]+f[pos[v]+j])%MOD;
    			if(u==1)continue;
    			down(pos[u]+k,pos[u]+mxd[u]-dpt[u]),sum[pos[u]+k]=(sum[pos[u]+k-1]+f[pos[u]+k])%MOD;
    			f[pos[u]+k]=f[pos[u]+k]*((j>0)*sum[pos[v]+j-1]+1)%MOD+f[pos[v]+j]*sum[pos[u]+k-1]%MOD+f[pos[u]+k]*f[pos[v]+j]%MOD;
    			f[pos[u]+k]%=MOD;
    		}
    		if(u==1)continue;
    		if(mxd[v]<mxd[u])(h[pos[u]+mxd[v]-dpt[u]+1]*=(sum[pos[v]+mxd[v]-dpt[v]]+1))%=MOD;
    	}
    }
    
    int main()
    {
    	n=getint();
    	for(int i=1;i<n;i++)
    	{
    		int u=getint(),v=getint();
    		G[u].push_back(v),G[v].push_back(u);
    	}
    	dfs1(1,0),dfs2(1,0);
    	solve(1,0);
    	for(int i=2;i<=mxd[1];i++)down(i,mxd[1]),sum[i]=(i>2)*sum[i-1]+f[i];
    	long long ans=1;
    	for(int i=0;i<=n;i++)pd[i]=1,h[i]=1;
    	for(int i=0;i<G[1].size();i++)
    	{
    		int u=G[1][i];
    		for(int j=2;j<=mxd[u];j++)
    		{
    			if(h[j]!=1)pd[j]=pd[j]*h[j]%MOD,h[j+1]=h[j+1]*h[j]%MOD,h[j]=1;
    			tmp[pos[u]+j-2]=pd[j-1];
    		}
    		for(int j=2;j<=mxd[u];j++)pd[j]=pd[j]*(sum[pos[u]+j-2]+1)%MOD;
    		if (mxd[u]<n)(h[mxd[u]+1]*=(sum[pos[u]+mxd[u]-2]+1))%=MOD;
    	}
    	for(int i=0;i<=n;i++)pd[i]=1,h[i]=1;
    	for(int i=G[1].size()-1;~i;i--)
    	{
    		int u=G[1][i];
    		for(int j=2;j<=mxd[u];j++)
    		{
    			if(h[j]!=1)pd[j]=pd[j]*h[j]%MOD,h[j+1]=h[j+1]*h[j]%MOD,h[j]=1;
    			ans+=tmp[pos[u]+j-2]*f[pos[u]+j-2]%MOD*(pd[j]-pd[j-1])%MOD;
    		}
    		for(int j=2;j<=mxd[u];j++)pd[j]=pd[j]*(sum[pos[u]+j-2]+1)%MOD;
    		if(mxd[u]<n)(h[mxd[u]+1]*=(sum[pos[u]+mxd[u]-2]+1))%=MOD;
    	}
    	printf("%lld\n",((g[1]-ans)%MOD+MOD)%MOD);
    }
    

  • 相关阅读:
    java代码操作word模板并生成PDF
    接口httpClient 以及HttpClient与CloseableHttpClient之间的区别
    公司项目启动的时候连接数据库问题
    浏览器报400Bad Request异常
    数据库配置文件默认数据库连接设置
    代码中的mysql语法问题
    java代码实现文件的下载功能
    SringBoot启动报日志配置错误logback检测异常
    动态拼接手机号
    [面试] 面试官问你的职业生涯规划是什么,该如何回答?
  • 原文地址:https://www.cnblogs.com/IzayoiDoyo/p/13405121.html
Copyright © 2020-2023  润新知