Build a tree
题目链接:Build a tree
官方题解:
从最下层开始模拟到最上层就可以了。
除了最底层之外,每一层最多有三种节点,
第一种是以这个节点为根的树是满k叉树,第二种是不满的k叉树,第三种也是满k叉树,不过比第一种少了一层。
sz1表示第一种节点的子树大小(不过一旦没有了第一种节点,它就表示第二种节点),sum1表示有多少个这种节点
sz2,sum2,sz3,sum3同理
因此,边模拟边异或即可
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n,k;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&n,&k);
if(k==1)//对于链来说要特判,否则直接模拟会TLE
{
switch(n%4)
{
case 1:
printf("1\n");
break;
case 2:
printf("%lld\n",n+1);
break;
case 3:
printf("0\n");
break;
case 0:
printf("%lld\n",n);
break;
}
}
else
{
LL tot,ans=0,sz1=0,sz2=0,sz3=0,sum1=0,sum2=0,sum3=0;
for(tot=1; n; tot*=k)//找到最底层
{
n-=tot;
if(n<tot*k)
break;
}
if(n)
{
sum1=n,sz1=1;
if(n&1)
ans=1;//最后一层的结果
}
for(; tot>0; tot/=k)//从倒数第二层开始
{
if(sum1<k)
sz1=sum1*sz1+sz2+(k-sum1-sum2)*sz3+1,sum1=1,sz2=0,sum2=0;
else
{
if(sum1%k)
sz2=sum1%k*sz1+sz2+(k-sum1%k-sum2)*sz3+1,sum2=1;
else if(sum2)
sz2=sz2+(k-1)*sz3+1;
sz1=sz1*k+1;
sum1=sum1/k;
}
sz3=sz3*k+1;
sum3=tot-sum1-sum2;
if(sum1&1)
ans^=sz1;
if(sum2&1)
ans^=sz2;
if(sum3&1)
ans^=sz3;
}
printf("%lld\n",ans);
}
}
return 0;
}