HDU 6121Build a tree

来源:互联网 发布:linux安装hadoop2.7.3 编辑:程序博客网 时间:2024/06/05 15:00

题意:给你一个n个节点的k叉树,每个节点的值为以其为根节点的子树的节点数。问所有节点的异或值是多少。
分析:算是模拟吧,就从下递推到上面就行。除了最后一层外,每层的节点最多有三种,第一种是以这个节点为根的子树是一颗满k叉树;第二种是不满的k叉树,这种在每一层最多只有一个;第三种是也是满k叉树,但是会比第一种少一层。边推边异或就好了 。

#include<cstdio>using namespace std;typedef long long ll;ll n, m, k, s, t, ans;ll n1, s1, n2, s2, n3, s3;int main(){    int T;    scanf("%d", &T);    while(T--){        ans = 0;        n1 = s1 = n2 = s2 = n3 = s3 = 0;        scanf("%lld%lld", &n, &k);        if(k == 1) {            printf("%lld\n",n%4==1?1:(n%4==2?n+1:(n%4==3?0:n)));            continue;        }        for(s = 1; n; s *= k){            n -= s;            if(n / s < k) break;        };        if(n){            n1 = n, s1 = 1;            if(n & 1) ans = 1;        }        for( ; s > 0; s /= k){            if(n1 < k){                s1 = n1 * s1 + s2 + (k - n1 - n2) * s3 + 1,n1 = 1, n2 = 0, s2 = 0;            }else {                if(n1 % k){                    s2 = n1 % k * s1 + (k - n1 % k - n2) * s3 + s2 + 1;                    n2 = 1;                }else if(n2){                    s2 = s2 + (k - 1) * s3 + 1;                 }                s1 = s1 * k + 1;                n1 = n1 / k;            }            s3 = s3 * k + 1;            n3 = s - n1 - n2;            if(n1 & 1) ans ^= s1;            if(n2 & 1) ans ^= s2;            if(n3 & 1) ans ^= s3;        }        printf("%lld\n", ans);    }}
原创粉丝点击