zoukankan      html  css  js  c++  java
  • hdu 6121---Build a tree(深搜+思维)

    题目链接

    Problem Description
    HazelFan wants to build a rooted tree. The tree has n nodes labeled 0 to n1, and the father of the node labeled i is the node labeled i1k. HazelFan wonders the size of every subtree, and you just need to tell him the XOR value of these answers.
     
    Input
    The first line contains a positive integer T(1T5), denoting the number of test cases.
    For each test case:
    A single line contains two positive integers n,k(1n,k1018).
     
    Output
    For each test case:
    A single line contains a nonnegative integer, denoting the answer.
     
    Sample Input
    2
    5 2
    5 3
     
    Sample Output
    7
    6
     
     
    题意:有一颗树,节点编号0~n-1 ,节点 i 的父亲节点编号 ⌊i1k⌋ ,求所有子树大小相异或值?
     
    思路:可以发现这是一棵完全 k 叉树 ,那么所有叶子节点高度差最多为1,且所有最高层叶子都靠左。那么我们从上向下找最高最靠右的叶子,然后回溯时计算:这时当前节点子树的大小特殊,其左边的所有同层次节点子树大小相同,其右边的所有同层次节点子树大小相同,所以对于每一层只需要考虑三种不同的节点子树。
     
             官方题解:
           
     
     

    代码如下:(唉,比赛时代码没调出来,赛后才调完,有点可惜~)

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef  long long LL;
    const LL N=1e18+5;
    LL cnt[70];
    LL pw[70];
    LL n,k,m;
    int deep;
    LL ans=0;
    LL L,R,mid;
    
    void dfs(int x)
    {
        if(x>deep) return ;
        dfs(x+1);
        LL pos=(cnt[x]-1)%k; ///left brother;
    
        int f=(cnt[x]-1)&1;
        if(f) ans^=L;
    
        LL cR=pw[x]-cnt[x];
        f=cR&1;
        if(f) ans^=R;
    
        ans^=mid;
    
        mid=pos*L+mid+1+(k-pos-1)*R;
        L=L*k+1;
        R=R*k+1;
    }
    
    int main()
    {
        int T; cin>>T;
        while(T--)
        {
           scanf("%lld%lld",&n,&k);
           if(k == 1){
                if(n%4 == 0) ans = n;
                else if(n%4 == 1) ans = 1;
                else if(n%4 == 2) ans = n+1;
                else if(n%4 == 3) ans = 0;
                printf("%lld
    ",ans);
                continue;
           }
           LL tmp=1;
           m=n-1; pw[0]=1;
           for(int i=1;i<70;i++)
           {
               tmp=tmp*k; pw[i]=tmp;
               if(m<tmp || tmp<0 ) {  pw[i]=N; deep=i; break; }
               m-=tmp;
           }
           cnt[deep]=m;
           if(m==0) { deep--; cnt[deep]=pw[deep]; m=cnt[deep]; }
           for(int i=deep-1;i>=0;i--)
           {
               cnt[i]=(m+k-1)/k;
               m=cnt[i];
           }
           L=1; mid=1; R=0;
           ans=0;
           dfs(0);
           printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    软件工程实践2020_个人作业 —— 软件评测
    软件工程实践2020_结对第二次作业 —— 某次疫情统计可视化的实现
    最受欢迎的 Git 分支工作流
    结对编程作业
    软件案例分析作业
    个人项目
    个人博客作业1
    第一次作业-热身!
    面向对象第三单元
    电梯作业总结
  • 原文地址:https://www.cnblogs.com/chen9510/p/7367747.html
Copyright © 2011-2022 走看看