hdu 6121 Build a tree(k叉树的异或和)

来源:互联网 发布:全球cs专业排名知乎 编辑:程序博客网 时间:2024/06/05 03:25

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;}
原创粉丝点击