首页 > 其他分享 >P9745 「KDOI-06-S」树上异或

P9745 「KDOI-06-S」树上异或

时间:2024-04-19 20:56:28浏览次数:25  
标签:P9745 06 int 枚举 times i64 异或 断边 define

P9745 「KDOI-06-S」树上异或

位运算trick+树形 dp

看到题目中贡献的计算,可以想到乘法分配律,也就是一个连通块的乘积可以直接乘在当前所有方案的权值之和上

可以考虑特殊性质:。那么树的问题就变成了序列问题。容易设 \(f_i\) 表示 \(i\) 以前的节点的所有断边方案权值和。转移直接枚举断边:\(f_i=\sum f_j\times(s_i\oplus s_j)\)。\(s_i=\bigoplus\limits_{j=1}^i a_j\)。

复杂度是 \(O(n^2)\)。瓶颈在于断边的枚举,同时又注意到位运算的相关性质还没有用到,考虑这个方面的优化,一个经典 trick 就是按二进制位计算贡献,这样做的原理一个是位运算是按位计算,一个是答案的计算满足分配律。

可以设 \(g_{i,j,0/1}\) 表示考虑到第 \(i\) 个位置,与 \(i\) 相连的连通块在第 \(j\) 位二进制位上的值为 \(0/1\),并且强制 \(i\) 向后连边的断边方案权值和(不计算 \(i\) 的影响)。这样做的好处就是转移不再需要枚举断边。转移有:

\(g_{i,j,0}=g_{i,j,0}\times(f_{i-1}+g_{i-1,j,0})+g_{i,j,1}\times g_{i-1,j,1}\)

\(g_{i,j,1}=g_{i,j,1}\times(f_{i-1}+g_{i-1,j,0})+g_{i,j,0}\times g_{i-1,j,1}\)

\(f_{i}=\sum\limits_{j=0}^{63} 2^j\times g_{i,j,1}\)

实际上在 \(g\) 转移时,\(f_i\) 转移的就是 \(i\) 单独成为一个连通块的情况,而 \(g\) 转移的就是与前面的连通块相连时的贡献,可以发现这样的两种情况是不存在交集的。最后 \(f_i\) 的计算就是计算 \(i\) 所在连通块每一位上的贡献(与先前的枚举断边的方法等价),这里转换了计算贡献的角度。

考虑树上的做法,其实完全类似,就是把式子搬到树上,这里就不列举,重点还是序列问题时的思路。

具体在写转移的时候要注意把当前状态存起来。

复杂度 \(O(n\log V)\)。

#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 = 5e5 + 10, mod = 998244353;
int n;
i64 a[N];
i64 f[N];
int g[N][65][2];
std::vector<int> e[N];
void dfs(int u, int fa) {
	for(int i = 0; i <= 63; i++) g[u][i][(a[u] >> i) & 1] = 1;
	for(auto v : e[u]) {
		if(v == fa) continue;
		dfs(v, u);
		for(int i = 0; i <= 63; i++) {
			i64 u0 = g[u][i][0], u1 = g[u][i][1]; //先存起来,防止转移错误
			g[u][i][0] = (u0 * (g[v][i][0] + f[v]) % mod + u1 * g[v][i][1] % mod) % mod;
			g[u][i][1] = (u0 * g[v][i][1] % mod + u1 * (f[v] + g[v][i][0]) % mod) % mod; 
		}
	}
	for(int i = 0; i <= 63; i++) f[u] = (f[u] + (1ll << i) % mod * g[u][i][1]) % mod;
}
void Solve() {
	std::cin >> n;
	for(int i = 1; i <= n; i++) std::cin >> a[i];
	for(int i = 2; i <= n; i++) {
		int u;
		std::cin >> u;
		e[u].pb(i), e[i].pb(u);
	}
	dfs(1, 0);
	std::cout << f[1] << "\n";
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	Solve();

	return 0;
}

标签:P9745,06,int,枚举,times,i64,异或,断边,define
From: https://www.cnblogs.com/FireRaku/p/18146760

相关文章

  • 106.React SSR(服务器端渲染)实践指南
    106.ReactSSR(服务器端渲染)实践指南极客前端探索者前沿技术的探索者,编码艺术的实践者​关注他 1人赞同了该文章随着前端技术的发展,单页应用(SPA)已经成为了前端开发的主流形式。然而,在某些场景下,如首屏加载速度、SEO优化等方面,SPA仍然存在着一些......
  • 【爆款推荐】初中中考阅读理解难题一网打尽!句子结构深度解析+答案揭秘,助你轻松冲刺高
    PDF格式公众号回复关键字:ZKYDT006原文1Whatdidmanypeopledowhentheyvisitedthemuseum?解析1What什么manypeople很多人do做whentheyvisitedthemuseum当他们参观博物馆时当人们参考博物馆时,他们做什么?2Manypeoplefromallovertheworldvi......
  • 30天【代码随想录算法训练营34期】第七章 回溯算法part06 (● 332.重新安排行程 ● 51
    332.重新安排行程木有看懂,没视频所以也没看懂51.N皇后自己写出来还是有难度的classSolution:defsolveNQueens(self,n:int)->List[List[str]]:result=[]#存储最终结果的二维字符串数组chessboard=['.'*nfor_inrange(n)]#初始化......
  • JTCR-继承-06
    继承基础classA{inti;voidm(){//body}}classBextendsA{intk;voidn(){//body}}没有类可以成为其自身的超类(superclass)。子类不能访问超类中的private成员。超类类型变量可以引用派生自该超类的子类对象,但是使用该变量只......
  • web server apache tomcat11-06-Host Manager App
    前言整理这个官方翻译的系列,原因是网上大部分的tomcat版本比较旧,此版本为v11最新的版本。开源项目从零手写实现tomcatminicat别称【嗅虎】心有猛虎,轻嗅蔷薇。系列文章webserverapachetomcat11-01-官方文档入门介绍webserverapachetomcat11-02-setup启动web......
  • 06-智能调度-运输任务
    1.任务调度1.1分析通过前面的实现,已经将相同转运节点的写入到了Redis的队列中,谁来处理呢?这就需要调度任务进行处理了,基本的思路是:查询待分配任务的车辆→计算运力→分配运单→生成运输任务→生成司机作业单也就是说,调度是站在车辆角度推进的。1.2实现这里采......
  • 06-排序 分页 过滤
    排序查询多条和全部才会用到排序排序关键字:ordering查询字符串查询字符串(QueryString)是指在URL中以问号(?)开始的部分,用于向服务器传递参数。它由一个或多个键值对组成,每个键值对之间用&符号分隔。例如,在以下URL中,查询字符串是?page=2&category=books:在django种如......
  • 06_QT网络编程之UDP通信
    QT网络编程之UDP通信udp编程​ udp不分客户端和服务器,只需要使用一个类QUdpSocket。代码Udp.pro#-------------------------------------------------##ProjectcreatedbyQtCreator2024-04-13T23:07:41##-------------------------------------------------QT......
  • 构建之法06
    在阅读完第六章后,我深感敏捷开发的思想和实践方法对我的工作有很大的启发。在我的实际工作中,我也尝试了一些敏捷开发的做法。首先,我更加注重与团队成员的沟通和协作。我们定期召开面对面的会议,讨论项目的进展、遇到的问题以及下一步的计划。这种沟通方式不仅提高了我们的工作效率......
  • MyBatis-06-Spring的SqlSession和原始区别
    DefaultSqlSession这个就不说了,SQL执行是调用执行器Executor执行SqlSessionTemplate构造函数,虽然没有立即创建SqlSession传入代理拦截器SqlSessionInterceptor,但是拦截器是一个实例内部类,可以访问到SqlSessionFactory并且SqlSessionTemplate不支持commit、rollback......