zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",ans);
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    JavaSE 基础 第51节 定义自己的异常
    JavaSE 基础 第50节 Java中的异常链
    JavaSE 基础 第49节 手动抛出异常
    JavaSE 基础 第48节 Java中的异常声明
    JavaSE 基础 第47节 获取异常信息
    JavaSE 基础 第46节 异常的分类
    JavaSE 基础 第45节Java异常快速入门
    JavaSE 基础 第44节 引用外部类的对象
    JavaSE 基础 第43节 静态内部类
    通用爬虫
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7376427.html
Copyright © 2011-2022 走看看