P9745 「KDOI-06-S」树上异或 题解
P9745 「KDOI-06-S」树上异或 题解
这题一看就不是很可做,先考虑部分分。
对于一条链的情况,我们可以枚举上一个断边的位置,然后转移。
一看数据范围,估计和值域有关,所以考虑
然后转移就枚举每一个儿子选或不选即可,例如
分别表示选
思路
考虑把上述思路扩展到
用
最后用方案数乘上
代码
实现的时候要注意用临时变量存一下
另外由于每一条边
时间复杂度:
// Problem: P9745 「KDOI-06-S」树上异或
// Contest: Luogu
// Author: Moyou
// Copyright (c) 2023 Moyou All rights reserved.
// Date: 2023-10-15 21:59:52
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
// #define int long long
using namespace std;
const int N = 5e5 + 10, mod = 998244353;
int f[N][61][2], g[N], n;
long long a[N];
vector<int> G[N];
signed main() {
n = read();
for(int i = 1; i <= n; i ++) a[i] = read();
for(int i = 2; i <= n; i ++) G[read()].push_back(i);
for(int u = n; u; u --) {
for(int i = 0; i < 60; i ++) f[u][i][a[u] >> i & 1] = 1;
for(auto v : G[u]) {
for(int i = 0; i < 60; i ++) {
int a = f[u][i][0], b = f[u][i][1];
f[u][i][0] = (1ll * f[u][i][0] * (g[v] + f[v][i][0]) + 1ll * f[v][i][1] * b) % mod;
f[u][i][1] = (1ll * f[u][i][1] * (g[v] + f[v][i][0]) + 1ll * f[v][i][1] * a) % mod;
}
}
for(int i = 0, p = 1; i < 60; i ++, p = p * 2 % mod) {
g[u] = (1ll * g[u] + 1ll * p * f[u][i][1]) % mod;
}
}
printf("%d\n", g[1]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!