HDU 6121 Build a tree (技巧)

来源:互联网 发布:ubuntu usb启动盘制作 编辑:程序博客网 时间:2024/06/15 02:56

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

25 25 3

 

Sample Output

76

 

题意

有一棵 n 个节点的 k 叉树,求所有子树大小的异或值。

 

思路

考虑任意一个高度为 h 的完全 k 叉树

对于根节点的 k 个孩子构成的 k 个子树

一定有一部分构成了高度为 h1 的完全 k 叉树,另一部分构成了高度为 h2 的完全 k 叉树。


通过递推我们可以得出:

  • cnt[i] ,第 i 层的节点个数
  • sum[i] ,高为 i 的满 k 叉树节点个数
  • xor[i] ,高为 i 的满 k 叉树所有子树异或和

我们知道, xx=0 ,一个数自身的偶数次异或值为 0 ,奇数次异或值等于它本身。

因此我们设 F(x,y) 为将 x 连续异或 y 次,显然其结果与 y 的奇偶性有关。

在满 k 叉树阶段, xor[dep]=sum[dep]F(xor[dep1],k) ,而在其他阶段,我们只需要递归将这颗树分解为若干个满 k 叉子树同样处理即可。

 

AC 代码

#include<bits/stdc++.h>typedef __int64 LL;using namespace std;const int maxn =105;LL cnt[maxn];       // 第 i 层的节点个数LL sum[maxn];       // 高为 i 的满 k 叉树节点个数LL xxor[maxn];      // 高为 i 的满 k 叉树所有子树异或和LL n,k;inline LL F(LL a,LL b){    return b&1?a:0;}LL dfs(LL dep,LL add){    if(dep==0)return 0;    return (sum[dep] + add)^F(sum[dep],add/cnt[dep])^F(sum[dep-1],k-1-add/cnt[dep])^dfs(dep-1,add%cnt[dep]);}LL solve(){    if(k==1)        // 对 1 特判    {        int mo = n%4;        if(mo==0)            return n;        else if(mo==1)            return 1;        else if(mo==2)            return n+1;        else            return 0;    }    int dep=1;    sum[dep]=cnt[dep]=xxor[dep]=1;    while((n-sum[dep])/k>=cnt[dep])     // 枚举深度(所有满节点的层)    {        dep++;        cnt[dep] = cnt[dep-1]*k;        sum[dep] = sum[dep-1] + cnt[dep];        xxor[dep] = sum[dep]^F(xxor[dep-1],k);    }    return dfs(dep,n-sum[dep]);}int main(){    int T;    cin>>T;    while(T--)    {        LL ans;        cin>>n>>k;        ans=solve();        cout<<ans<<endl;    }    return 0;}
原创粉丝点击