首页 > 其他分享 >P9437 『XYGOI round1』一棵树

P9437 『XYGOI round1』一棵树

时间:2024-04-16 21:56:59浏览次数:23  
标签:sz fa P9437 times i64 int XYGOI round1 mod

P9437 『XYGOI round1』一棵树

trick+换根dp

对于此类 「将数字顺次写下」 计算贡献的题目,通常按位考虑,并且考虑每个数作为 开头/结尾 时的贡献,方便计算。

因此,我们在这题中考虑每个数作为结尾时的贡献。那么这题就转化成:计算以 \(u\) 为根并且以 \(a_u\) 为结尾的贡献。明显的换根 dp。

首先考虑处理出各个子树中的贡献,设 \(f_u\) 表示在 \(u\) 子树中,以 \(a_u\) 为结尾的贡献。显然有:

\(f_u=a_u+\sum (f_v\times b_u+sz_v\times a_u)\)

其中 \(a_u\) 为题中所给,\(b_u\) 表示 \(a_u\) 的位数,\(sz_u\) 为子树大小。

考虑如何换根,也就是计算 \(fa_v\) 子树对 \(v\) 的贡献。这里将 \(fa_v\) 写为 \(u\),有:

\(f_v=f_v+(f_u-f_v\times b_u-sz_v\times a_u)\times b_u+(sz_1-sz_v)\times a_u\)

答案 \(ans=\sum f_u\),复杂度 \(O(n)\)。

#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define fi first
#define se second
#define pb push_back

typedef long long i64;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10, mod = 998244353;
int n;
i64 ans, c[N], f[N], sz[N], b[N], a[N];
std::vector<int> e[N];
void dfs1(int u, int fa) {
	sz[u] = 1, f[u] = a[u];
	for(auto v : e[u]) {
		if(v == fa) continue;
		dfs1(v, u);
		f[u] = (f[u] + f[v] * b[u] % mod + sz[v] * a[u] % mod) % mod;
		sz[u] += sz[v];
	}
}
void dfs2(int u, int fa) {
	ans = (ans + f[u]) % mod;
	for(auto v : e[u]) {
		if(v == fa) continue;
		f[v] = (f[v] + (f[u] - f[v] * b[u] % mod + mod - sz[v] * a[u] % mod + mod) * b[v] % mod + (sz[1] - sz[v]) * a[v] % mod) % mod;
		dfs2(v, u);
	}
}
void Solve() {
	std::cin >> n;
	c[1] = 10;
	for(int i = 2; i <= 9; i++) c[i] = c[i - 1] * 10;
	for(int i = 1; i <= n; i++) {
		std::cin >> a[i];
		if(!a[i]) b[i] = 10;
		else {
			int cnt = 0;
			i64 now = a[i];
			while(now) {
				now /= 10;
				cnt++;
			}
			b[i] = c[cnt];
		}
	}
	for(int i = 2; i <= n; i++) {
		int x;
		std::cin >> x;
		e[x].pb(i), e[i].pb(x);
	}
	dfs1(1, 0);
	dfs2(1, 0);
	std::cout << ans << "\n";
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	Solve();

	return 0;
}

标签:sz,fa,P9437,times,i64,int,XYGOI,round1,mod
From: https://www.cnblogs.com/FireRaku/p/18139294

相关文章

  • cfEduRound163div2--D题解
    D-TandemRepeats?题意:做法:因为字符串长度较少,可以考虑枚举。or--动态规划voidsolve(){//D枚举//枚举!!!!!!!!!!stringstr;cin>>str;intn=str.size(),ans=0;for(inti=1;i<=n/2;i++){//枚举一半!!!intcnt=0;for(intj=0;......
  • ZOI round1 数轴
    不错的思维题。为了将问题一般化,令\(N=0\),若\(N\ne0\),则可以将\(N\)视为原点,令\(x_i\leftarrowx_i-N\)。我们要求解走\(t\)个\(1\)单位从原点走到\(x\)的方案数。显然,走\(1\)单位可以走到\(1,-1\)。同样,走\(2\)单位可以走到\(2,0,-2\),其中走到\(0\)的方......
  • NSSRound16
    NSSRound16RCE但是没有完全RCE审题审核代码,简单的md5绕过。知识点md5绕过,命令组合,shell里``中的内容会被当成代码执行知识详解md5等于的绕过方法数组绕过a[]=1&b[]=2,0e绕过弱比较,md5后的值以0e开头即可绕过。$a==md5$a=0e215962017其md5后的值也为0e开头......
  • SMU 2024 winter round1
    题目链接A.直接输出#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=1e5+10;voidsolve(){cout<<"Goodcodeisitsownbestdocumentation."<<'\n';}signedmain(){ios::sync_with_st......
  • SMU 2024 winter round1
    7-1最好的文档#include<bits/stdc++.h>usingnamespacestd;usingi32=int32_t;i32main(){ios::sync_with_stdio(false),cin.tie(nullptr);cout<<"Goodcodeisitsownbestdocumentation.";return0;}7-2自动编程#includ......
  • 【牛客周赛】round14赛后总结
    碎碎念赛时没出题(真可恶吖)在上晚自习,补了一下。ACD都套着字符串的外壳,差点直接劝退,后来仔细一读发现和字符串没什么关系...大概字符串的用处是为了劝退我这种有些怂字符串的人叭。A.小红的环形字符串题意:对于给定的环形字符串s,可以删除相邻的两个相同字母,问最多删除多少个字......
  • CF补题round1
    目录luoguP4233射命丸文的笔记CF1498ETwoHousesluoguP4233射命丸文的笔记link如果一个竞赛图含有哈密顿回路,则称这张竞赛图为值得记录的。从所有含有n个顶点(顶点互不相同)的,值得记录的竞赛图中等概率随机选取一个。求选取的竞赛图中哈密顿回路数量的期望值。性质1:......
  • CF_EduRound155小丑寄
    一句话总结:A题理解错了,数据又水,所以寄了。过程:22:35开题。22:40怎么还没加载出来??急急急22:42哦,严格大于,但是主宾对调了,乐乐乐乐乐乐乐,cout<<ans;\(\rightarrow\)cout<<ans-1;22:45一发过。。。22:45-23:38啥事没有。23:38开E题23:50左右好像有点思路......
  • P9437 『XYGOI round1』一棵树 题解
    首先这是一道很明显的换根dp。首先注意到要拼接数,所以我们可以先处理出\(num_i=10^{x}\),使得\(10^x>a_i>10^{x-1}\),这样方便我们后面算贡献。我们以这棵树为例子来推状态转移方程。先假设\(dp_u\)表示以\(1\)为根时,从\(u\)的子树的点到\(u\)的权值和。那么\[......
  • Codeforces EduRound153 Editorial
    A如果有\(()\)那么肯定是不合法的有两种很简单的构造,()()()()...()和((((...)))),如果一个串是第一种构造的子串那么一定不是第二种构造的子串,反之亦然。使用python取之B把\(m\%k\)的余数补齐,再把多出来的\(1\)价格regularcoins\(m\)个一组f使用python取之C......