一起看很美的日落!

news/2025/1/26 18:36:05/文章来源:https://www.cnblogs.com/onlyblues/p/18690873

一起看很美的日落!

题目描述

牛可乐有一棵由 $n$ 个结点构成的树,第 $i$ 个节点的权值为 $a_i$。

我们定义一个连通块 $\mathbb{V}$ 的权值为:

  • 当前连通块中两两结点的权值异或和,即 $\sum\limits_{i,j \in \mathbb{V}}{a_i \oplus a_j}$;

你需要计算全部连通块的权值之和。由于答案可能很大,请将答案对 $(10^9 +7)$ 取模后输出。

此题中的连通块定义为:对于树上的任意一个点集 $\mathbb{S}$,如果 $\mathbb{S}$ 中的任意两点 $u,v$ 之间存在一条路径,且路径上的所有点都在 $\mathbb{S}$ 中,则称 $\mathbb{S}$ 是一个连通块。

输入描述:

第一行输入一个整数 $n \, (1 \leq n \leq 10^5 )$ 代表树上的节点数量。

第二行输入 $n$ 个整数 $a_1,a_2, \ldots ,a_n \, (1 \leq a_i \leq 10^9)$ 代表每个节点的权值。

此后 $n−1$ 行,第 $i$ 行输入两个整数 $u_i,v_i \,​ (1 \leq u_i,v_i \leq n,u_i \ne v_i)$ 代表树上第 $i$ 条边连接节点 $u_i$ 和 $v_i$。

输出描述:

输出一个整数,代表全部连通块的权值和。答案可能很大,请将答案对 $(10^9+7)$ 取模后输出。

示例1

输入

3
5 2 1
1 2
1 3

输出

50

说明

在这个样例中,一共有 $6$ 个连通块,每一个连通块的权值依次为:

  • $\{1\}$,记为 $\mathbb{V}_1$,权值为 $\sum\limits_{i,j \in \Bbb V_1}(a_i \oplus a_j)=a_1\oplus a_1=0$;
  • $\{1,2\}$,记为 $\mathbb{V}_2$,权值为 $\sum\limits_{i,j \in \Bbb V_2}(a_i \oplus a_j)=(a_1\oplus a_1)+(a_1\oplus a_2)+(a_2\oplus a_1)+(a_2\oplus a_2)=14$;
  • $\{1,3\}$,记为 $\mathbb{V}_3$,权值为 $\sum\limits_{i,j \in \Bbb V_3}(a_i \oplus a_j)=(a_1\oplus a_1)+(a_1\oplus a_3)+(a_3\oplus a_1)+(a_3\oplus a_3)=8$;
  • $\{1,2,3\}$,记为 $\mathbb{V}_4$,权值为 $\sum\limits_{i,j \in \Bbb V_4}(a_i \oplus a_j)=28$;
  • $\{2\}$,记为 $\mathbb{V}_5$,权值为 $\sum\limits_{i,j \in \Bbb V_5}(a_i \oplus a_j)=a_2\oplus a_2=0$;
  • $\{3\}$,记为 $\mathbb{V}_6$,权值为 $\sum\limits_{i,j \in \Bbb V_6}(a_i \oplus a_j)=a_3\oplus a_3=0$;

示例2

输入

4
5 6 3 1
1 2
1 3
2 4

输出

142

 

解题思路

  大概想了下发现很复杂要维护很多东西,以为错了就直接看题解,没想到还真这么做。

  假设以节点 $1$ 作为整颗树的根。题目中的连通块其实就是以任意节点为根的子树,因此我们可以按子树的根把所有的连通块(子树)分成 $n$ 类,然后分别求每一类连通块的结果最后累加即可。由于涉及到位运算,我们可以对节点的权值进行拆位分别处理,这样每个节点的权值只有 $0$ 和 $1$ 两种情况,最后将算出的结果乘以相应的 $2$ 的次幂,就是该位对答案的贡献。

  现在有一个集合 $s$,元素只有 $0$ 和 $1$,数量分别记为 $c(s,0)$ 和 $c(s,1)$。根据异或的性质,该集合中任意两个元素的异或值的和就是 $c(s,0) \times c(s,1)$,记为 $f(s)$。现在有集合 $t$ 要与 $s$ 进行合并,$0$ 和 $1$ 的数量就变成了 $c(s,0) + c(t,0)$ 和 $c(s,1) + c(t,1)$,异或值的和就是

\begin{align*}
f(s \cup t) &= (c(s,0) + c(t,0)) \times (c(s,1) + c(t,1)) \\
&= c(s,0) \times c(s,1) + c(t,0) \times c(t,1) + c(s,0) \times c(t,1) + c(s,1) \times c(t,0) \\
&= f(s) + f(t) + c(s,0) \times c(t,1) + c(s,1) \times c(t,0)
\end{align*}

  假设有 $g(s)$ 个集合 $s_i$ 要与 $g(t)$ 个集合 $t_j$ 进行合并,那么所有合并结果的异或值的和就是

\begin{align*}
\sum\limits_i{\sum\limits_j{f(s_i \cup t_j)}} &= \sum\limits_i{\sum\limits_j{(c(s_i,0) + c(t_j,0)) \times (c(s_i,1) + c(t_j,1))}} \\
&= \sum\limits_j{\sum\limits_i{f(s_i)}} + \sum\limits_i{\sum\limits_j{f(t_j)}} + \sum\limits_i{c(s_i,0)} \times \sum\limits_j{c(t_j,1)} + \sum\limits_i{c(s_i,1)} \times \sum\limits_j{c(t_j,0)} \\
&= g(t)\sum\limits_i{f(s_i)} + g(s)\sum\limits_j{f(t_j)} + \sum\limits_i{c(s_i,0)} \times \sum\limits_j{c(t_j,1)} + \sum\limits_i{c(s_i,1)} \times \sum\limits_j{c(t_j,0)} \\
\end{align*}

  同理合并后的集合数量就是 $g(s) \times g(t)$,所有集合 $0$ 的数量就是 $g(t)\sum\limits_i{c(s_i,0)} +g(s)\sum\limits_j{c(t_j,0)}$,所有集合 $1$ 的数量就是 $g(t)\sum\limits_i{c(s_i,1)} +g(s)\sum\limits_j{c(t_j,1)}$。

  假设我们现在处理的是第 $k$ 位,用 $a_{u,k}$ 表示二进制下节点 $u$ 权值第 $k$ 位的值。假设 $u$ 有 $m_u$ 个子节点,记为 $v_1, v_2, \ldots, v_{m_u}$。那么以 $u$ 为根的子树就可以通过以 $v_i$ 为根的所有子树进行任意组合得到,可以用 dp 求出以 $u$ 为根的所有子树的任意两个节点异或值的和。

  定义 $f(u,i)$ 表示以 $v_1, v_2, \ldots, v_i$ 为根的子树组合得到的所有以 $u$ 为根的子树的任意两个节点异或值的和,$g(u,i)$ 表示以 $v_1, v_2, \ldots, v_i$ 为根的子树组合得到的所有以 $u$ 为根的子树的数量,$c(u,0,i)$ 和 $c(u,1,i)$ 分别表示以 $v_1, v_2, \ldots, v_i$ 为根的子树组合得到的所有以 $u$ 为根的子树的权值为 $0$ 和 $1$ 的节点数量。根据以 $v_i$ 为根的子树进行状态划分,可以把以 $v_i$ 为根的子树看成上述若干个集合 $t_j$,把以 $v_1, v_2, \ldots, v_{i-1}$ 为根的子树组合得到的所有以 $u$ 为根的子树看成若干个集合 $s_i$,$s_i$ 与 $t_j$ 两两进行合并。

  初始只有一个节点 $u$,此时有 $f(u,0) = a_{u,k}$,$g(u,0) = 1$,$c(u,a_{u,k},0) = 1$,$c(u,\neg a_{u,k},0) = 0$。参考上面的式子,状态转移方程就是

\begin{cases}
\begin{align*}
f(u,i) &= f(u,i-1) + g(v_i, m_{v_i}) \cdot f(u,i-1) + g(u,i-1) \cdot f(v_i,m_{v_i}) + c(u,0,i-1) \cdot c(v_i,1,m_{v_i}) + c(u,1,i-1) \cdot c(v_i,0,m_{v_i}) \\
c(u,0,i) &= c(u,0,i-1) + g(v_i,m_{v_i}) \cdot c(u,0,i-1) + g(u, i-1) \cdot c(u,0,i-1) \\
c(u,1,i) &= c(u,1,i-1) + g(v_i,m_{v_i}) \cdot c(u,1,i-1) + g(u, i-1) \cdot c(u,1,i-1) \\
g(u,i) &= g(u,i-1) + g(u,i-1) \cdot g(v_i,m_{v_i})
\end{align*}
\end{cases}

  在代码实现中省略了所有状态的最后一维。

  那么第 $k$ 位对答案的贡献就是 $2^k\sum\limits_{i=1}^{n}{f(i,m_i)}$。最后要求的答案就是 $2 \cdot \sum\limits_{k=0}^{29}2^k\sum\limits_{i=1}^{n}{f(i,m_i)}$,多乘一个 $2$ 是因为上述考虑的是两个节点的组合,而题目要求考虑两个节点的排列。

  AC 代码如下,时间复杂度为 $O(n \log{A})$:

#include <bits/stdc++.h>
using namespace std;typedef long long LL;const int N = 1e5 + 5, M = N * 2, mod = 1e9 + 7;int a[N];
int h[N], e[M], ne[M], idx;
int f[N], g[N], c[N][2];void add(int u, int v) {e[idx] = v, ne[idx] = h[u], h[u] = idx++;
}void dfs(int u, int p, int k) {f[u] = 0, g[u] = 1, c[u][a[u] >> k & 1] = 1, c[u][~a[u] >> k & 1] = 0;for (int i = h[u]; i != -1; i = ne[i]) {int v = e[i];if (v == p) continue;dfs(v, u, k);f[u] = (f[u] + 1ll * f[u] * g[v] + 1ll * f[v] * g[u] + 1ll * c[u][0] * c[v][1] + 1ll * c[u][1] * c[v][0]) % mod;c[u][0] = (c[u][0] + 1ll * c[u][0] * g[v] + 1ll * c[v][0] * g[u]) % mod;c[u][1] = (c[u][1] + 1ll * c[u][1] * g[v] + 1ll * c[v][1] * g[u]) % mod;g[u] = (g[u] + 1ll * g[u] * g[v]) % mod;}
}int main() {int n;cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];}memset(h, -1, sizeof(h));for (int i = 0; i < n - 1; i++) {int u, v;cin >> u >> v;add(u, v), add(v, u);}int ret = 0;for (int i = 0; i < 30; i++) {dfs(1, 0, i);for (int j = 1; j <= n; j++) {ret = (ret + f[j] * (1ll << i)) % mod;}}cout << ret * 2 % mod;return 0;
}

 

参考资料

  2025牛客寒假算法基础集训营2 出题人题解:https://blog.nowcoder.net/n/906fd00ff386438b9d63013a3760e73a

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/875569.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

哈工深准备复试~代码复健

去年年前过完了c语言基础,初始算了下分成绩还不错,现在寒假在家准备复试 东西真的忘得干干净净了,因为是跨考,所以算是零基础吧,每天刷刷代码题,就当复健了

Avalonia系列文章之再试牛刀

通过前一篇文章,已经了解了AvaloniaUI的环境安装以及项目创建,磨刀不误砍柴工,今天继续进行Avalonia基础知识学习,如有不足之处,还请指正。通过前一篇文章,已经了解了AvaloniaUI的环境安装以及项目创建,磨刀不误砍柴工,今天继续进行Avalonia基础知识学习,如有不足之处…

2025.1.25

本次错误分析: 本次错误主要集中于:对于题目读题不认真,做题不细心,题目中明显要求了举例说明,但是本题给的答案却没有明显的给出例子,导致本题扣分 日后改正:应该多多端正自己的态度,做到对待任何题目犹如对待考场上的题目一样认真

思通数科舆情系统的预警设置

思通数科舆情系统中的预警设置功能在现代企业和政府的舆情管理中具有重要的市场应用和战略意义。通过精准的预警机制,思通数科舆情系统能够实时监控舆情动向,提前识别潜在的风险,帮助企业与政府机构及时做出反应,最大限度地降低负面影响。1、什么是预警 网络预警是指从危机…

第十二章 质量管理(2025年详细解析版)

目录导语什么是质量管理?关注两个方面:12.1 管理基础什么是质量?质量与等级质量等级预防胜于检查预防胜于检查质量管理质量方针质量目标质量管理水平有效性递增质量管理体系GB/T 19000系列标准全面质量管理项目质量管理新实践12.2 项目质量管理过程过程概述项目质量管理过…

STM32 GPIO使用

1.GPIO是什么 GPIO(General Purpose Input/Output)通用输入输出,是STM32开发板中的通用输入输出接口,用于连接外部设备。 GPIO 有时候简称为“IO口”。通用,说明它是常见的。 输入输出,就是说既能当输入口使用,又能当输出口使用。 端口,就是元器件上的一个引脚。输入模式…

html图片音频视频标签

1 图片 src 规定显示图像的URL height 图像高度 width 图像宽度 2 音频 src 规定音频的URL controls 显示播放控件 3 视频 src 规定视频的URL controls 显示播放控件 例子:

C#Socket通讯采用UTF8编码发送接收中英文混合消息出现乱码???

采用UTF8编码发送和接收中英文混合消息,中文呈???的乱码?,请问各位大咖问题出在哪里了?如下图:

面向长文本的多模型协作摘要架构:多LLM文本摘要方法

多LLM摘要框架在每轮对话中包含两个基本步骤:生成和评估。这些步骤在多LLM分散式摘要和集中式摘要中有所不同。在两种策略中,k个不同的LLM都会生成多样化的文本摘要。然而在评估阶段,多LLM集中式摘要方法使用单个LLM来评估摘要并选择最佳摘要,而分散式多LLM摘要则使用k个LLM进行…