zoukankan      html  css  js  c++  java
  • HDU 6121 Build a tree —— 2017 Multi-University Training 7

    HazelFan wants to build a rooted tree. The tree has nn nodes labeled 0 to n−1, and the father of the node labeled i is the node labeled  . 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)T(1≤T≤5), denoting the number of test cases. 
    For each test case: 
    A single line contains two positive integers n,k(1n,k1018)n,k(1≤n,k≤1018). 
    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

    题意:画一下题目介绍的树,发现这是一个k叉树,那么题目要求所有子树大小的异或和。
    思路:我们从序号为n的节点开始,往上求异或和。n计算到某一层时,对于处在n节点左边的节点(子树),它们是t+1层的满k叉树,在右边的节点(子树)是t层的满二叉树,
    满二叉树的大小可以通过打表得到。根据异或计算的性质,大小相同的子树进行异或,有奇数个进行异或时结果为该子树的大小,偶数个时为0。
    而对n位置节点的子树来说,不是满二叉树就是非满二叉树,而且在计算这个子树大小时一旦它在某一层是非满二叉树,接下来往上它就一直是非满二叉树。
    还有,k==1时特判一下。
    具体实现参看代码。

    AC代码:
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    typedef long long LL;
    LL n, k;
    LL num[100];
    int main()
    {
        int T;
        cin>>T;
        num[0]=1;
        while(T--)
        {
            scanf("%lld %lld", &n, &k);
            if(k==1){
                if(n==1)
                    printf("%d
    ", 1);
                else if(n==2)
                    printf("%d
    ",3);
                else if(n==3)
                    printf("%d
    ", 0);
                else 
                {
                    int k=n%4;
                    if(k==0)
                        printf("%lld
    ", n);
                    else if(k==1)
                        printf("%d
    ", 1);
                    else if(k==2)
                        printf("%lld
    ", n+1);
                    else
                        printf("%d
    ", 0);
                }
                continue;
            }
            n--;
            int level=0,t=0;
            LL lm=0, rm=0;
            while(rm<n){
                t++;
                lm=rm+1;
                rm=lm*k;
                num[t]=rm+1;
            }
            LL res=0,left,right,s=n+1,m;
            t=0; 
            bool flag=0;
                LL mid=n%k;//mid判断是否为满k叉树, m为非满k叉树的大小 
                left=n-mid-lm+1;
                //cout<<left<<endl;
                if(left&1){
                    res^=num[0];
                }
                if(mid&1)
                    res^=num[0];
                if(mid)
                    flag=1;
                    
                m=(n-(n-1)/k*k)*num[0]+1;
                //cout<<m<<endl;
                while(n)
                {
                    
                    //cout<<res<<'*'<<endl;
                    
                    t++;
                    //cout<<t<<' '<<m<<endl;
                    
                    n=(n-1)/k;
                    if(n<=0)
                        break;
                    
                    mid=n%k; 
                    lm=(lm-1)/k;
                    rm=(rm-1)/k;
                    //cout<<lm<<' '<<n<<' '<<rm<<endl;
                    right=rm-n;
                    left=n-lm+1;
                    if(flag||mid){
                        flag=1;
                        left--;
                        res^=m;
                    }
                    
                    if(left&1)
                        res^=num[t];
                    if(right&1)
                        res^=num[t-1];
                    m+=(n-(n-1)/k*k-1)*num[t]+(((n-1)/k+1)*k-n)*num[t-1]+1;
                    
                }
            res^=s;
            printf("%lld
    ", res);
        }
        return 0;
    }
    
    
    


  • 相关阅读:
    【Android Developers Training】 49. 轻松录制视频
    【Android Developers Training】 48. 轻松拍摄照片
    【Android Developers Training】 47. 序言:拍摄照片
    【Android Developers Training】 46. 处理音频外放设备
    【Android Developers Training】 45. 控制音频焦点
    【Android Developers Training】 44. 控制你应用的音量和播放
    【Android Developers Training】 43. 序言:管理音频播放
    【Android Developers Training】 42. 从另一台设备接收文件
    【Android Developers Training】 41. 向另一台设备发送文件
    Linux开发常见问题:GCC:链接器输入文件未使用,因为链接尚未完成
  • 原文地址:https://www.cnblogs.com/MasterSpark/p/7413163.html
Copyright © 2011-2022 走看看