【题解 树形dp 拆位】 树上异或

2023-10-22 08:12

本文主要是介绍【题解 树形dp 拆位】 树上异或,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

「KDOI-06-S」树上异或

题目描述

给定一棵包含 n n n 个节点的树,第 i i i 个点有一个点权 x i x_i xi

对于树上的 n − 1 n-1 n1 条边,每条边选择删除或不删除,有 2 n − 1 2^{n-1} 2n1 种选择是否删除每条边的方案。

对于每种删除边的方案,设删除后的图包含 k k k 个连通块,定义这个方案的权值为图中连通块点权异或和的乘积。形式化地说,若这张图包含连通块 C 1 , C 2 , … , C k C_1,C_2,\ldots,C_k C1,C2,,Ck,其中 C i C_i Ci 是第 i i i 个连通块的顶点集合,设 v i = ⨁ u ∈ C i x u v_i=\bigoplus_{u\in C_i} x_u vi=uCixu,则这个方案的权值为 v 1 × v 2 × ⋯ × v k v_1\times v_2\times \cdots\times v_k v1×v2××vk

求这 2 n − 1 2^{n-1} 2n1 种删除边的方案的权值之和,答案对 998 244 353 998~244~353 998 244 353 取模。

输入格式

从标准输入读入数据。

输入的第一行包含一个正整数 n n n,表示树的节点个数。

第二行 n n n 个非负整数 x 1 , x 2 , … , x n x_1,x_2,\ldots,x_n x1,x2,,xn,表示每个点的点权。

第三行 n − 1 n-1 n1 个正整数 f 2 , f 3 , … , f n f_2,f_3,\ldots,f_n f2,f3,,fn,表示节点 i i i f i f_{i} fi 之间有一条无向边。

输出格式

输出到标准输出。

输出包含一行一个整数,表示所有 2 n − 1 2^{n-1} 2n1 种删除边的方案的权值之和,答案对 998 244 353 998~244~353 998 244 353 取模。

样例 #1

样例输入 #1

3
1 2 3
1 1

样例输出 #1

19

样例 #2

样例输入 #2

5
3 4 5 6 7
1 1 2 2

样例输出 #2

5985

提示

【样例解释 #1】

有四种删除边的方案:

  • 不删除边:图有且仅有一个连通块,权值为 1 ⊕ 2 ⊕ 3 = 0 1\oplus2\oplus3=0 123=0
  • 删除 ( 1 , 2 ) (1,2) (1,2) 一条边:图包含两个连通块,权值为 ( 1 ⊕ 3 ) × 2 = 4 (1\oplus3)\times2=4 (13)×2=4
  • 删除 ( 1 , 3 ) (1,3) (1,3) 一条边:图包含两个连通块,权值为 ( 1 ⊕ 2 ) × 3 = 9 (1\oplus2)\times3=9 (12)×3=9
  • 删除 ( 1 , 2 ) (1,2) (1,2) ( 1 , 3 ) (1,3) (1,3) 两条边:图包含三个连通块,权值为 1 × 2 × 3 = 6 1\times2\times3=6 1×2×3=6

所有方案权值的总和为 0 + 4 + 9 + 6 = 19 0+4+9+6=19 0+4+9+6=19

【样例 #3】

见选手目录下的 xor/xor3.inxor/xor3.ans

这个样例满足测试点 6 ∼ 7 6\sim7 67 的条件限制。

【样例 #4】

见选手目录下的 xor/xor4.inxor/xor4.ans

这个样例满足测试点 8 8 8 的条件限制。

【样例 #5】

见选手目录下的 xor/xor5.inxor/xor5.ans

这个样例满足测试点 9 9 9 的条件限制。

【样例 #6】

见选手目录下的 xor/xor6.inxor/xor6.ans

这个样例满足测试点 19 ∼ 21 19\sim21 1921 的条件限制。


【数据范围】

对于所有数据保证: 1 ≤ n ≤ 5 × 1 0 5 1\leq n\leq5\times10^5 1n5×105 0 ≤ x i ≤ 1 0 18 0\leq x_i\leq10^{18} 0xi1018 1 ≤ f i < i 1\leq f_i<i 1fi<i

测试点编号 n ≤ n\leq n x i x_i xi特殊性质
1 ∼ 2 1\sim2 12 12 12 12 ≤ 1 0 9 \leq10^9 109
3 3 3 2000 2000 2000 = 1 =1 =1
4 4 4 1 0 5 10^5 105 = 1 =1 =1A
5 5 5 1 0 5 10^5 105 = 1 =1 =1B
6 ∼ 7 6\sim7 67 1 0 5 10^5 105 = 1 =1 =1
8 8 8 1 0 5 10^5 105 ≤ 7 \leq7 7A
9 9 9 1 0 5 10^5 105 ≤ 7 \leq7 7B
10 ∼ 11 10\sim11 1011 1 0 5 10^5 105 ≤ 7 \leq7 7
12 ∼ 16 12\sim16 1216 200 200 200 ≤ 8191 \leq8191 8191
17 17 17 1 0 5 10^5 105 ≤ 1 0 9 \leq10^9 109A
18 18 18 1 0 5 10^5 105 ≤ 1 0 9 \leq10^9 109B
19 ∼ 21 19\sim21 1921 1 0 5 10^5 105 ≤ 1 0 9 \leq10^9 109
22 ∼ 25 22\sim25 2225 5 × 1 0 5 5\times10^5 5×105 ≤ 1 0 18 \leq10^{18} 1018
  • 特殊性质 A:保证对于任意 1 < i ≤ n 1< i\le n 1<in f i = i − 1 f_i=i-1 fi=i1
  • 特殊性质 B:保证对于任意 1 < i ≤ n 1< i\le n 1<in f i = 1 f_i=1 fi=1

【提示】

⊕ \oplus 表示按位异或运算。

本题输入输出量较大,请使用适当的 I/O 方式。

请注意常数因子对程序运行效率产生的影响。


分析:

树上问题一下子不好分析,我们首先从链的问题来考虑
一一枚举所有的断边情况,时间复杂度是 O ( 2 n ) O(2^n) O(2n),显然爆炸

我们考虑dp
f i f_i fi表示第i个点的答案( ∑ ∏ \sum\prod ∑∏)
我们考虑枚举前面的断边,
f i = ∑ f j ∗ ( s i x o r s j ) f_i=\sum f_j*(s_i xor s_j) fi=fj(sixorsj)

这样 O ( n 2 ) O(n_2) O(n2)就能把问题全部解决,但是还是不够

怎么办?
我们考虑拆位
g i , j , 0 / 1 g_{i,j,0/1} gi,j,0/1表示第i个点,i所在的联通块的点权二进制的第j位为0/1时,与i所在连通块断开的连通块的答案是多少

对于当前边,我们有断和不断两个选择,如果不断,那么i的前一个点也包含在了i所在的连通块上,需要根据情况去转移对应点的01值,如果当前边断掉,那么前一个点的二进制值就当做0来考虑

于是我们进行以下转移:
在这里插入图片描述

感谢大佬的博客
而后f加起来即可


#include<bits/stdc++.h>
using namespace std;#define ll long longll Mo = 998244353;const int N = 5e5+10;
int n;
ll a[N],f[N],g[N][64][2];
struct Node{int y,Next;
}e[2*N];
int len , Linkk[N];#define gc getchar()
ll read(){ll s = 0 , ff = 0; char ch = gc;while (ch < '0' || ch > '9') ff|=ch == '-' , ch = gc;while (ch >= '0' && ch <= '9') s = s*10+ch-48 , ch = gc;return ff?-s:s;
} void Insert(int x,int y){e[++len] = (Node){y,Linkk[x]};Linkk[x] = len;
}void Dfs(int x,int faa){for (int i = 0; i < 64; i++){int xx = (a[x]>>i)&1;g[x][i][xx] = 1;}for (int j = Linkk[x]; j; j = e[j].Next){int y = e[j].y;if (y == faa) continue;Dfs(y,x);for (int i = 0; i < 64; i++){int t0 = g[x][i][0] , t1 = g[x][i][1];g[x][i][0] = (t0*((g[y][i][0]+f[y]))+t1*g[y][i][1])%Mo;g[x][i][1] = (t1*((g[y][i][0]+f[y]))+t0*g[y][i][1])%Mo;}}for (int i = 0; i < 64; i++)f[x] = (f[x]+(1ll<<i)%Mo*g[x][i][1])%Mo;return;
}signed main(){n = read();for (int i = 1; i <= n; i++) a[i] = read();for (int i = 2,x; i <= n; i++)x = read(),Insert(i,x),Insert(x,i);Dfs(1,0);printf("%lld",f[1]%Mo);return 0;
}

这篇关于【题解 树形dp 拆位】 树上异或的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/260210

相关文章

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

uva 10154 DP 叠乌龟

题意: 给你几只乌龟,每只乌龟有自身的重量和力量。 每只乌龟的力量可以承受自身体重和在其上的几只乌龟的体重和内。 问最多能叠放几只乌龟。 解析: 先将乌龟按力量从小到大排列。 然后dp的时候从前往后叠,状态转移方程: dp[i][j] = dp[i - 1][j];if (dp[i - 1][j - 1] != inf && dp[i - 1][j - 1] <= t[i]

uva 10118 dP

题意: 给4列篮子,每次从某一列开始无放回拿蜡烛放入篮子里,并且篮子最多只能放5支蜡烛,数字代表蜡烛的颜色。 当拿出当前颜色的蜡烛在篮子里存在时,猪脚可以把蜡烛带回家。 问最多拿多少只蜡烛。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cs

uva 10069 DP + 大数加法

代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <cl

uva 10029 HASH + DP

题意: 给一个字典,里面有好多单词。单词可以由增加、删除、变换,变成另一个单词,问能变换的最长单词长度。 解析: HASH+dp 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

XTU 1233 n个硬币连续m个正面个数(dp)

题面: Coins Problem Description: Duoxida buys a bottle of MaiDong from a vending machine and the machine give her n coins back. She places them in a line randomly showing head face or tail face o

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int