第七次多校联合hdu6121Build a tree

来源:互联网 发布:祝你一路顺风 知乎 编辑:程序博客网 时间:2024/05/16 14:28

题目

题意:有一棵nnn个点的有根树,标号为000到n−1n-1n−1,iii号点的父亲是i1k号点,求所有子树大小的异或和。

题解:思路和代码都来自这个人→传送门

但是这位大佬好像没有提到满k叉树,好像弄错了完全k叉树的定义。。。。。。(不敢造次)

大致思路就是分别讨论满k叉树的情况和完全k叉树的情况。递归一下。代码还是比较好弄明白的。
(大致弄懂了思路,但是感觉自己还是敲不出来,而且思路也是非常神奇了。所以就基本照敲了代码。。。)
(我还是太菜了啊。。。。ORZ)

#include<bits/stdc++.h>using namespace std;#define ll long longconst int maxn=65;ll cnt[maxn],sum[maxn],x[maxn],n,k;ll F(ll a, ll b)///返回b个a异或的值{    if(b%2==1)        return a;    return 0;}ll dfs(ll dep,ll add)//dep:完全k叉树的层数 add:dep层完全k叉树下面的多余节点{    if(dep==0)        return 0;    retun (sum[dep}+add)^F(sum[dep],add/cnt[dep])^F(sum[dep-1],k - 1 - add/cnt[dep]) ^ dfs(dep-1,add%cnt[dep]);    ///这四个数分别代表dep层所有节点数,dep层满k叉树节点数,dep-1层满k叉节点数,和完全k叉树。}ll slove(){    if(k==1)///打表找规律    {        if(k%4==0)return n;        if(k%4==1)return 1;        if(k%2==0)return n+1;        return 0;    }    int dep=1;    cnt[dep]=sum[dep]=x[dep]=1;    while((n-sum[dep])/k>=cnt[dep])///建立满k叉树    //if(所有节点 - 已经用来构成dep层完全k叉树的节点)即剩下的节点还可以继续构成dep+1层完全k叉树    {        dep++;        cnt[dep]=cnt[dep-1]*k;        sun[dep]=sum[dep-1]+cnt[dep];        x[dep]=sum[dep]^F(x[dep-1],k);    }    return dfs(dep,n-sum[dep]);}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%lld %lld",&n,&k);        printf("%lld\n",slove());    }}
原创粉丝点击