首页 > 其他分享 >题解:P9437 一棵树

题解:P9437 一棵树

时间:2024-07-23 10:32:32浏览次数:16  
标签:fa P9437 题解 sum 一棵树 int size 节点 mod

题目传送门

明显的换根 dp,感觉是道不错的换根 dp 练习题。

题意

一棵 \(n\) 个节点的树,点带权,定义 \(w(x,y)=\overline {a_x\dots a_y}\) 。

求 \(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}w(i,j)\bmod 998244353\)。

思路

我们不妨先求出 \(i=1\) 时的 \(\sum w(i,j)\),再求 \(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}w(i,j)\)。

设 \(f_u\) 为其子树每个点走到 \(x\) 的总贡献,定义 \(\operatorname{get}(a_u)\) 为 \(a_u\) 的位数,不难得出转移方程:

\[f_u=\sum\limits_{v\in son} f_v \times \operatorname{get}(a_u)+size_u\times a_x \]

这样我们就可以求出 \(i=1\) 时的 \(\sum w(i,j)\)。朴素的,我们可以直接求 \(n\) 次得到最终的答案,但是这样 \(\mathcal{O(n^2)}\) 的复杂度是不能接受的。

从 \(i=1\) 推到整棵树,考虑换根 dp,发现这几个条件都很好换根转移。

具体的,我们设 \(g_u\) 为整棵树走到 \(u\) 的贡献。考虑一个节点,假设我们已经得知了其父节点的 \(g\),并且也得知了其子树内点的贡献,所以剩余需要求出子树外的答案。

子树外节点到其父节点的贡献和为其父节点的 \(g\) 减去此节点及其子树对父节点的贡献,而子树外节点到其本身的贡献都比父节点多个本身,所以需要再乘一个 \(10^{\mid a_x \mid}\)。形式化的:

\[g_u=(g_{fa}-(f_u\times \operatorname{get}(a_{fa})+size_x\times a_{fa}))\times \operatorname{get}(a_{fa})+(n-size_u)\times a_u+f_u \]

答案即为 \(\sum g\),复杂度 \(\mathcal{O(n)}\),注意开 long long 和一步一模防止爆炸。

代码

#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int N=1e6+5;
const int mod=998244353;
inline int read();
int n,a[N],cnt,head[N];
int f[N],size[N],g[N],ans;
struct E{
	int to,next,w;
}edge[N<<1];
void add(int u,int v)
{
	edge[++cnt].next=head[u];
	edge[cnt].to=v;
	head[u]=cnt;
}
int get(int x)
{
	if(x==0) return 10;
	int cnt=0;
	while(x>=1)
	{
		x/=10;
		cnt++;
	}
	return pow(10,cnt);
}
void dfs0(int x,int fa)
{
	size[x]=1;
	for(int i=head[x];i;i=edge[i].next)
	{
		int to=edge[i].to;
		if(to==fa) continue;
		dfs0(to,x);
		f[x]=(f[x]+f[to]*get(a[x]))%mod;
		size[x]+=size[to];
	}
	f[x]=(f[x]+size[x]*a[x])%mod;
}
void dfs(int x,int fa)
{
	for(int i=head[x];i;i=edge[i].next)
	{
		int to=edge[i].to;
		if(to==fa) continue;
		g[to]=(((g[x]-(f[to]*get(a[x])%mod+a[x]*size[to])%mod)*get(a[to]))%mod+((n-size[to])*a[to])%mod+f[to])%mod;
		dfs(to,x);
	}
}
signed main()
{
	n=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read(); 
	}
	for(int i=1;i<n;i++)
	{
		int x;
		x=read();
		add(x,i+1);
		add(i+1,x);
	}
	dfs0(1,0);
	g[1]=f[1];
	dfs(1,0);
	for(int i=1;i<=n;i++)
	{
		ans=(ans+g[i])%mod; 
	}
	printf("%lld",ans);
	return 0;
}

inline int read()
{
	int x=0,f=1;
	char ch;
	ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-') f=-f;ch=getchar();}
	while(ch<='9'&&ch>='0')
	{
		x=(x<<1)+(x<<3)+(ch&15);
		ch=getchar();
	}
    return x*f;
}

标签:fa,P9437,题解,sum,一棵树,int,size,节点,mod
From: https://www.cnblogs.com/yzxgg/p/18317716

相关文章

  • [SDOI2012] 走迷宫 题解
    [SDOI2012]走迷宫题目描述Morenan被困在了一个迷宫里。迷宫可以视为\(n\)个点\(m\)条边的有向图,其中Morenan处于起点\(s\),迷宫的终点设为\(t\)。可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿着一条从该点出发的有向边,到达另一个点。这样,Morenan走的步数可能......
  • 2024年暑期2024牛客暑期多校训练营1 C和H题解
    C题SumofSuffixSums题目大意:开始是给你一空数组,要经历q次操作,每次操作都会给出两个数字t和v,其中要从数组末尾去走元素t次,最后加上元素v。定义si=ai+ai+1+ai+2+ai+3+......+an,最后求s1+s2+s3+.......+sn的总和。最后答案注意取模。 题解:注意到sum的总和其实就......
  • CF512D Fox And Travelling 题解
    Description给定一张\(n\)个点\(m\)条边的无向图。一个点只有当与它直接相连的点中最多只有一个点未被选择过时才可被选择。询问对于每个\(k\in[0,n]\),有序选择\(k\)个点的方案数。\(n\le100\),\(m\le\frac{n(n-1)}2\),答案对\(10^9+9\)取模。Solution容易发......
  • [COCI2015-2016#1] UZASTOPNI 题解
    前言题目链接:洛谷。题意简述一棵有根树,节点数\(n\leq10^5\),每个点有权值\(v_i\leq2000\),现在选出一些点,满足:一个点的父亲点若未被选择则其不能被选择。所选点的集合内不能有相同的权值。对于每一个选择的点,其子树中所有被选择点的权值必须可以构成公差为\(1\)的等......
  • 2024牛客暑期多校训练营2(部分题目题解)
    2024牛客暑期多校训练营2(部分题目题解)C.RedWalkingonGrid题意:给定只有红白的2*n个格子,只能走红色各自且只能上下左右走,问最多可以走多少红色格子。题解:左右走:dp[0][i]=dp[0][i-1]+1;上下走:intk1=dp[0][i];intk2=dp[1][i];dp[0][i]=max(dp[0][i],k2+......
  • 20240722题解
    孩子们,我回来了......
  • Luogu P4310 绝世好题 题解 [ 绿 ] [ 线性 dp ] [ 单调队列优化 ] [ 二进制优化 ]
    题目:绝世好题。暴力dp显然\(O(n^2)\)转移即可。单调队列优化观察到只有某二进制位两个数都为\(1\)时才能转移,因此我们把每个二进制位开一个单调队列,然后对于一个数\(a\),找到它是\(1\)的二进制位并选其单调队列的队头进行转移,在这之后把这个数加入符合要求的单调队列......
  • 题解:CF1349B Orac and Medians
    洛谷|CF刷一些CF2000,进行一个录的记。思路记录首先观察到数列里的数不能凭空产生,所以初始序列必须含\(k\)。由于两个数的中位数是较小的那个,所以只要有一个与数列里的\(k\)相邻且比\(k\)大的数,就可以扩展到整个序列。发现可以把第二条推广一下,不必要和\(k\)相邻,因......
  • SLF4J: Class path contains multiple SLF4J bindings 问题解决
    背景:springboot项目名称test,在使用slf4j后,服务启动报错 报错信息:SLF4J:ClasspathcontainsmultipleSLF4Jbindings.SLF4J:Foundbindingin[jar:file:/D:/Program%20Files/Java/.m2/repository/ch/qos/logback/logback-classic/1.2.7/logback-classic-1.2.7.jar!/or......
  • [CEOI2018] Lottery 题解
    前言题目链接:洛谷。题意简述给出序列\(a_1\ldotsa_n\)和常数\(l\leqn\),定义:\[\operatorname{dis}(i,j)=\sum_{k=0}^{l-1}[a_{i+k}\neqa_{j+k}]\qquad(i,j\in[1,n-l+1])\]每次询问一个\(k\),求对于所有\(i\in[1,n-l+1]\),求\(\sum......