2017多校联合第7场/hdu 6121 Build a tree(K叉树的异或和)+满K叉树的性质总结

来源:互联网 发布:linux 定时重启 编辑:程序博客网 时间:2024/06/18 01:08

Build a tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 937    Accepted Submission(s): 366


Problem Description
HazelFan wants to build a rooted tree. The tree has n nodes labeled 0 to n1, and the father of the node labeled i is the node labeled i1k. 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(1T5), denoting the number of test cases.
For each test case:
A single line contains two positive integers n,k(1n,k1018).
 

Output
For each test case:
A single line contains a nonnegative integer, denoting the answer.
 

Sample Input
25 25 3
 

Sample Output
76


参考题解 http://blog.csdn.NET/hackertom/article/details/77199170


当k=1时,需要特别处理。打表观察一下规律:

int get_ans(int n){    int ans=n;    for(int i=1;i<n;i++)        ans^=i;    return ans;}int main(){    for(int i=1;i<=48;i++)    {        cout<<get_ans(i)<<' ';        if(i%4==0)cout<<endl;    }    return 0;}
运行结果为
1 3 0 4 1 7 0 8 1 11 0 12 1 15 0 16 1 19 0 20 1 23 0 24 1 27 0 28 1 31 0 32 1 35 0 36 1 39 0 40 1 43 0 44 1 47 0 48 

可以观察到规律:

if(k==1)    {        if(n%4==1)cout<<"1"<<endl;        else if(n%4==2)cout<<n+1<<endl;        else if(n%4==3)cout<<"0"<<endl;        else cout<<n<<endl;    }

最多只有一个节点不是满K叉树,单独处理这个节点的子树,其余子树的各子树的异或和等于其子树的大小,递归处理这个子树;


#include <iostream>#include <algorithm>#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <string.h>#include <map>#include <set>#include <queue>#include <deque>#include <list>#include <bitset>#include <stack>#include <stdlib.h>#define lowbit(x) (x&-x)#define e exp(1.0)const int mod=1e9+7;const int inf=0x3f3f3f;//ios::sync_with_stdio(false);//    auto start = clock();//    cout << (clock() - start) / (double)CLOCKS_PER_SEC;typedef long long ll;typedef long long LL;using namespace std;//int get_ans(int n)//{  //  int ans=n;    //for(int i=1;i<n;i++)      //  ans^=i;    //return ans;//}int main(){    ios::sync_with_stdio(false);    //for(int i=1;i<=48;i++)//打表求1-n的异或    //{       // cout<<get_ans(i)<<' ';       // if(i%4==0)cout<<endl;    //}    int T;    cin>>T;    while(T--)    {        ll n,k;        cin>>n>>k;        if(k==1)        {            if(n%4==1)cout<<"1"<<endl;            else if(n%4==2)cout<<n+1<<endl;            else if(n%4==3)cout<<"0"<<endl;            else cout<<n<<endl;            continue;        }        ll ans=n;        while(1)        {            if(n-1<=k)//depth=1            {                if(n%2==0)// xor一个数两次等于不做任何处理                    ans^=1;                break;            }            ll x=1,now=1,full=1;            while(x>=0 && now>=0 && now+k*x<n)            {                x*=k;                now+=x;                full^=now;            }            ll l=(n-now-1)/x;//不满足k叉树的左边树的数量            ll r=k-l-1;            if(k%2==1)            {                if(l%2==1)ans^=full;                if(r%2==1)ans^=(full^now);            }            else            {                if(l%2==1)ans^=now;                if(r%2==1)ans^=(now-x);            }            n-=(l*now+r*(now-x)+1);            ans^=n;        }        cout<<ans<<endl;    }    return 0;}


阅读全文
0 0
原创粉丝点击