1. 程式人生 > >HDU 6121 Build a tree —— 2017 Multi-University Training 7

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

color thml 二叉樹 滿二叉樹 rst def 位置 實現 es2017

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\n", 1); else if(n==2) printf("%d\n",3); else if(n==3) printf("%d\n", 0); else { int k=n%4; if(k==0) printf("%lld\n", n); else if(k==1) printf("%d\n", 1); else if(k==2) printf("%lld\n", n+1); else printf("%d\n", 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\n", res); } return 0; }



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