「KDOI-06-S」题解

news/2024/9/20 2:34:44/文章来源:https://www.cnblogs.com/FRZ29/p/18415215

T2 树上异或

题面

分析

树形 DP 题

考虑一颗子树内部的某种割边方式,假设其被分为 \(n\) 个连通块,每个连通块的权值分别为 \(a_1, a_2, \dots, a_n\),那么该子树在这种割边方式下对答案的贡献就为 \(\prod_{i = 1}^{n} a_i\)

因此就可以从叶子向根不断合并,求出每种割边状态的值,时间复杂度为 \(O(2^{n - 1}n)\),期望得分 \(8\) 分。

这启示往树形 DP 的方向思考。

将每次定下割边的方法转变,考虑在 DP 过程中通过将两个连通块连接到一起,去遍历每一种状态。

这样,每回溯到一个点:

  1. 遍历该点的子树
  2. 把与该点之间存在割边的连通块与该点之前所找到的连通块合并
  3. 每次合并后求出该情况的贡献(如图,将蓝色连通块的权值异或在一起,然后计算结果)

实现困难,时间复杂度极高。

因为连通块对答案的贡献是 \(\prod_{i = 1} ^{n} a_i\) 的形式,故某子树除去被合并的连通块后不同情况产生的贡献是可以累加的。(答案是 \(a_1 b_1+\dots+a_1 b_n+a_2 b_1+\dots+a_n b_n\),即 \((a_1+\dots+a_n)(b_1+\dots+b_n)\))。

而合并连通块却无法这样优化。

对此,有一种方法能够快速地合并连通块——拆位。

具体来说,定义 \(f_{u, i, j}\) 表示以 \(u\) 所在的连通块的权值第 \(i\) 位为 \(j\) 时以 \(u\) 为根节点的子树除了\(u\) 所在的连通块其他连通块的乘积的值,定义 \(g_u\) 表示以 \(u\) 为根节点的子树对答案的贡献。

容易得到:$$g_u = \sum_{i = 0}^{63}f_{u, i, 1} \times 2^i$$,即 \(u\) 所在连通块第 \(i\) 位为 \(1\) 时,所有的割边方案的贡献。

故仅需考虑 \(f_{u, i, j}\) 的转移。

考虑当前遍历到 \(u\) 的儿子节点 \(v\),则:

  1. 如果不合并,则 \(v\) 的子树全都与 \(u\) 所在的连通块无关,那么 \(g_v\) 全都要乘到 \(f_{u, i, 0}\)
  2. 合并第 \(i\) 位为 \(1\) 的情况,如果连通块原本为 \(1\) ,则与该子树中第 \(i\) 位为 \(0\) 的异或后第 \(i\) 位仍然为 \(1\)。否则为与第 \(i\) 位为 \(1\) 的连通块异或。
  3. \(i\) 位为 \(0\) 则恰好相反。

即:

\[f_{u, i, 0} = f_{u, i, 0} \times g_{v} + f_{v, i, 0} \times f_{u, i, 0} + f_{v, i, 1} \times f_{u, i, 1} \]

\[f_{u, i, 1} = f_{u, i, 1} \times g_v + f_{v, i, 0} \times f_{u, i, 1} + f_{v, i, 1} \times f_{u, i, 0} \]

答案为 \(g_1\)

注意

本题空间较小,动态规划数组开 long long 会爆。

/*--------------------------------|        code by FRZ_29        ||          code  time          ||          2024/09/15          ||           13:42:20           ||             星期天            |--------------------------------*/#include <iostream>
#include <climits>
#include <cstdio>
#include <ctime>
typedef long long LL;using namespace std;void RD() {}
template<typename T, typename... U> void RD(T &x, U&... arg) {x = 0; int f = 1;char ch = getchar();while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();x *= f; RD(arg...);
}const int N = 5e5 + 5;
const int mod = 998244353;#define PRINT(x) cout << #x << "=" << x << "\n"
#define LF(i, __l, __r) for (int i = __l; i <= __r; i++)
#define RF(i, __r, __l) for (int i = __r; i >= __l; i--)int head[N], Next[N << 1], ver[N << 1], tot = 1;
int n, f[N][65][2], g[N];
LL a[N];void add(int u, int v) {ver[++tot] = v;Next[tot] = head[u], head[u] = tot;
}void dfs(int u, int _f) {LF(i, 0, 63) f[u][i][a[u] >> i & 1] = 1;for (int i = head[u]; i; i = Next[i]) {int v = ver[i];if (v == _f) continue;dfs(v, u);LF(i, 0, 63) {LL t0 = f[u][i][0], t1 = f[u][i][1];f[u][i][0] = (t0 * g[v] + t0 * f[v][i][0] + t1 * f[v][i][1]) % mod;f[u][i][1] = (t1 * g[v] + t1 * f[v][i][0] + t0 * f[v][i][1]) % mod;}}LF(i, 0, 63) g[u] = (g[u] + (1LL << i) % mod * f[u][i][1]) % mod;
}int main() {
//    freopen("read.in", "r", stdin);
//    freopen("out.out", "w", stdout);
//    time_t st = clock();RD(n);LF(i, 1, n) RD(a[i]);LF(u, 2, n) {int v; RD(v);add(u, v), add(v, u);}dfs(1, 0);printf("%d", g[1]);
//    printf("\n%dms", clock() - st);return 0;
}/* ps:FRZ弱爆了 */

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

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

相关文章

安卓签名校验机制

安卓签名校验机制 目录1 V1方案1.1 V1方案的安全性2 V2方案2.1 摘要计算过程 2.2 防回滚绕过3 V3方案 4 V4方案 5 签名实践5.1 keytool生成密钥库 5.2 jarsigner 5.3 apksigner6 引用安卓的签名校验机制共有三代。 9.0以上的系统会判断apk是否使用到V3版本的签名,如果有,那么…

胡鑫宇第一次作业

软件技术第一次作业作业属于哪个课程 https://edu.cnblogs.com/campus/zjlg/rjjc/作业的要求 发布一篇随笔,对自己进行简单介绍姓名 胡鑫宇学号 2022329301143班级 22电气工程及其自动化(2)一、个人介绍 1. 个人情况 大家好,我是电气工程及其自动化2班的胡鑫宇,来自河北邯…

安卓应用启动流程

安卓应用启动流程 目录1 冷启动热启动 2 zygote和SystemServer 3 应用启动流程简述(记得补充) 4 从点击图标到通知Zygote4.1 Launcher 4.2 Activity.java 4.3 Instrumentation.java 4.4 ActivityTaskManager.java 4.5 ActivityTaskManagerService.java 4.6 ActivityStarter.j…

痞子衡嵌入式:JLink命令行以及JFlash对于下载算法的作用地址范围认定QN

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是JLink命令行以及JFlash对于下载算法的作用地址范围认定。最近痞子衡在给一个 RT1170 客户定制一个 Infineon MirrorBit 类型 64MB Flash 的 SEGGER 下载算法,做完之后在 JFlash 下测试小数据下载没有问题,但…

安卓系统启动流程解析

安卓系统启动流程 目录1 init阶段1.1 FirstStage 1.2 SELinux Setup 1.3 SecondStage2 init.rc的配置 3 Zygote的启动3.1 app_process 3.2 Zygoteinit.java4 SystemServer 5 总结 6 引用光看分析文章还是不够的,还是要和实践结合。 1 init阶段 init 命令的入口是init/main.cpp…

安卓架构

安卓架构 目录1 Linux 内核层 2 硬件抽象层 HAL 3 Native C/C++ 库 && Android Runtime 4 Java Framework 层 5 System Apps 层1 Linux 内核层 Android 平台的基础是 Linux 内核。例如,ART 依靠 Linux 内核来执行底层功能。Linux 内核的安全机制为 Android 提供了相应…

陈柯烽的第一次作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/zjlg/rjjc这个作业的目标 建立一个属于自己的博客,介绍自己以及表达对课程的期望姓名-学号 陈柯烽-2022329301006软件技术基础第一次作业 一、自我介绍 1、基本信息我叫陈柯烽,来自浙江宁波,是自动化22级一班的学生,我…

chm 文件打开只显示目录,不显示内容

chm 文件打开只显示目录,不显示内容解决方法:解除锁定OK 了

【好用安全保密】不用插件,压缩js、html、css、code【一眼就会系列】【亲测有效】

​ 仅用离线版Notepad搞定。不用插件及辅助工具,有效保证了文件信息安全。 (一般发布版本都是无注释的-压缩文件和已编译文件。为了信息安全性,所有都是离线-区域网研发。) ​ 总结: 先把文本中注释去掉。 notepad++ 【编辑】-【空白字符操作】-【移除行首和行尾空格】 …

《密码系统设计》第二周

第二周预习报告 学习内容Head First C 嗨翻 C 语言 第8章 《Windows C/C++加密解密实战》第3,5章 第三章重点 3.4,3.5, 特别3.4.4 第五章重点 5.3.7 课程 mindmapAI 对学习内容的总结(1分) 要求让AI阅读学习内容并进行总结总结 1. Head First C 嗨翻 C 语言 第8章函数指针:…

活动召集丨实时多模态 AI Builder 团聚!RTE Open Day@S创上海,9.20/21

9 月 20~21 日,上海, S创上海 2024,看见不一样的创新和技术。这场年轻、多元、活力十足的科技盛会,将汇聚创业者、开发者、艺术家和众多无法定义边界的跨界者。RTE 开发者社区的 Builders 和 RTE Open Day 也将玩乐其中!「有一群人在一起,就很好」。 来到第四期的 RTE O…

问题1:pytorch版本不同,文件运行速度不同

好像新版本更快一点哦,为什么呢? 版本1: PyTorch version: 1.12.1Is CUDA available? TrueCUDA version: 11.3cuDNN version: 8302版本2: PyTorch version: 2.3.1+cu121Is CUDA available? TrueCUDA version: 12.1cuDNN version: 8907