Build a tree
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 609 Accepted Submission(s): 206
Problem Description
HazelFan wants to build a rooted tree. The tree has
n
nodes labeled
0
to
n−1
, and the father of the node labeled
i
is the node labeled
⌊i−1k⌋
. 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(1≤T≤5)
, denoting the number of test cases.
For each test case:
A single line contains two positive integers n,k(1≤n,k≤1018) .
For each test case:
A single line contains two positive integers n,k(1≤n,k≤1018) .
Output
For each test case:
A single line contains a nonnegative integer, denoting the answer.
A single line contains a nonnegative integer, denoting the answer.
Sample Input
2 5 2 5 3
Sample Output
7 6
Source
题意:有一棵树,第i个点的父亲节点为⌊i−1k⌋,求出所有子树大小的异或值
解题思路:可以明显发现这是一棵k叉完全树,最多只有一个不是满k叉树,那么只要对这个孩子就是递归即可,1的情况需要特判
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <bitset>
#include <stack>
#include <queue>
#include <unordered_map>
#include <functional>
using namespace std;
const int INF=0x3f3f3f3f;
#define LL long long
LL n,k,ans;
void dfs(LL x)
{
ans^=x;
x--;
LL p=1,xx=x,ans1=0,ans2=0,pp,sum=0,g=1;
while(xx>=p*k) {xx-=p*k,p*=k;}
pp=p/k;
while(pp)
{
sum+=g;
if(pp&1) ans1^=sum;
pp/=k;
g*=k;
}
if(xx%p) dfs(sum+xx%p);
sum=0,g=1,pp=p;
while(p)
{
sum+=g;
if(p&1) ans2^=sum;
p/=k;
g*=k;
}
LL cnt2=xx/pp;
LL cnt1=k-cnt2-(xx%pp?1:0);
if(cnt2&1) ans^=ans2;
if(cnt1&1) ans^=ans1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&n,&k);
if(k==1)
{
if(n%4==0) printf("%lld\n",n);
else if(n%4==1) printf("1\n");
else if(n%4==2) printf("%lld\n",n+1LL);
else printf("0\n");
continue;
}
ans=0;
dfs(n);
printf("%lld\n",ans);
}
return 0;
}