HDU 6121 Build a tree(完全K叉树)

Posted 谦谦君子,陌上其华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6121 Build a tree(完全K叉树)相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=6121

题意:
给你一颗完全K叉树,求出每棵子树的节点个数的异或和。

 

思路:

首先需要了解一些关于完全K叉树或满K叉树的一些知识:

对于每棵子树,只有三种情况:

①是满K叉树  ②不是满K叉树  ③叶子节点

并且非满K叉树最多只有一个,所以只需要将它进行特殊处理,具体看代码吧,说不清楚。代码参考了http://blog.csdn.net/my_sunshine26/article/details/77200282

当K=1时,树是链状的,需要打表找规律!

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<sstream>
 6 #include<vector>
 7 #include<stack>
 8 #include<queue>
 9 #include<cmath>
10 #include<map>
11 #include<set>
12 using namespace std;
13 typedef long long ll;
14 typedef pair<int,ll> pll;
15 const int INF = 0x3f3f3f3f;
16 const int maxn=100+5;
17 
18 ll n, k, ans;
19 ll num[maxn];
20 int depth;
21 
22 void init()
23 {
24     num[0]=0;
25     for(int i=1;i<=depth;i++)
26     {
27         num[i]=num[i-1]+pow((long double)k,(long double)i-1);  //因为pow默认是pow(int,int),没有对应long long的,所以我这儿用long double来代替了一下
28     }                                                          //当然这里可以自己用快速幂来计算
29 }
30 
31 int main()
32 {
33     //freopen("in.txt","r",stdin);
34     int T;
35     scanf("%d",&T);
36     while(T--)
37     {
38         scanf("%I64d%I64d",&n,&k);
39         if(k==1)                  //特判
40         {
41             ll tmp=n%4;
42             if(tmp==0) ans=n;
43             else if(tmp==1) ans=1;
44             else if(tmp==2) ans=n+1;
45             else ans=0;
46             printf("%I64d\\n",ans);
47             continue;
48         }
49 
50         depth=1;
51         ll tmp=n-1;
52         //计算树的深度
53         while(tmp>0)
54         {
55             tmp=(tmp-1)/k;
56             depth++;
57         }
58         init(); //预处理前i层的节点个数
59         ans=0;
60         ans^=(n-num[depth-1])&1; //先处理一下最后一层
61         depth--;
62         ll now=2;  //当前从下往上第几层
63         ll pos=(n-1-1)/k;
64         while(depth>0)
65         {
66             ll left=num[depth-1];  //当前层数最左边编号
67             ll right=num[depth]-1; //当前层数最右边编号
68             ll tmp1=num[now];      //左边树大小
69             ll tmp2=num[now-1];    //右边树大小
70             
71             //奇数才有贡献
72             if((pos-left)&1)   ans^=tmp1;
73             if((right-pos)&1)  ans^=tmp2;
74 
75             ll cnt=pos;
76             while(cnt<=(n-1-1)/k)  cnt=cnt*k+1;
77             ans^=(num[now-1]+n-cnt);  //单独处理临界点子树
78             now++;
79             depth--;
80             pos=(pos-1)/k;
81 
82         }
83         printf("%I64d\\n",ans);
84     }
85     return 0;
86 }

以上是关于HDU 6121 Build a tree(完全K叉树)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6121 Build a tree(找规律+模拟)

HDU 6121 Build a tree —— 2017 Multi-University Training 7

HDU2841 Visible Trees(容斥原理)

规律贪心数学HDU 5573 Binary Tree

hdu5606 tree (并查集)

hdu3999 The order of a Tree