您的位置:首页 > 产品设计 > UI/UE

【思维】2017多校训练七 HDU6121 Build a tree

2017-08-16 13:47 302 查看
http://acm.hdu.edu.cn/showproblem.php?pid=6121

【题意】

询问n个结点的完全k叉树,所有子树结点个数的异或和是多少

【思路】

一棵完全K叉树,对于树的每一层,我们可以分为三种结点:

满k叉树的结点

不满的k叉树

比第一种情况少一层的满结点的k叉树

1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 ll n,k;
5 ll ans;
6 ll kn[70],sz[70],full[70];
7 int cs;
8 void Pre()
9 {
10     //kn[i]=k^i
11     kn[0]=1;
12     for(int i=1;i<=cs;i++)
13     {
14         kn[i]=kn[i-1]*k;
15     }
16     //根结点为第一层,sz[i]为有i层的满k叉树有多少结点
17     sz[1]=1;
18     for(int i=2;i<=cs;i++)
19     {
20         sz[i]=sz[i-1]+kn[i-1];
21     }
22     //有i层的满k叉树所有子树结点大小的异或和
23     if(k&1)
24     {
25         full[0]=0;
26         for(int i=1;i<=cs;i++)
27         {
28             full[i]=full[i-1]^sz[i];
29         }
30     }
31     else
32     {
33         for(int i=1;i<=cs;i++)
34         {
35             full[i]=sz[i];
36         }
37     }
38 }
39
40 void dfs(int cur)
41 {
42     ans^=n;
43     ll lft=n-sz[cur];  //最后一层有多少个
44     ll l=lft/kn[cur-1];//多少个cur层的满k叉树
45     lft-=l*kn[cur-1];
46     if(lft==0)//没有不满的k叉树
47     {
48         if(l&1) ans^=full[cur];
49         if((k-l)&1) ans^=full[cur-1];
50         return;
51     }
52     if(l&1) ans^=full[cur];
53     if((k-l-1)&1) ans^=full[cur-1];
54     n--;n-=l*sz[cur];n-=(k-l-1)*sz[cur-1];
55     dfs(cur-1);
56 }
57 int main()
58 {
59     int T;
60     scanf("%d",&T);
61     while(T--)
62     {
63         ans=0;
64         scanf("%I64d%I64d",&n,&k);
65         //k=1特判,打表看出来的
66         if(k==1)
67         {
68             if(n%4==0)
69             {
70                 ans=n;
71             }
72             else if(n%4==1)
73             {
74                 ans=1;
75             }
76             else if(n%4==2)
77             {
78                 ans=n+1;
79             }
80             else
81             {
82                 ans=0;
83             }
84             printf("%I64d\n",ans);
85             continue;
86         }
87         //根结点为第一层,结点数为n的完全k叉树有cs层是满的
88         cs=0;
89         ll t=n;
90         while(t)
91         {
92             t--;
93             t/=k;
94             cs++;
95         }
96         //预处理
97         Pre();
98         ans=0;
99         //递归
100         dfs(cs);
101         printf("%I64d\n",ans);
102     }
103     return 0;
104 }


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: