2015上海现场赛 HDU 5573

这是一道在克隆赛碰到的题,当时看题队友以为是树形dp或者是暴搜,想了一下都没有思路,其实是一道 " 思维+二进制 "。

 

题目链接:传送门

题意:给你一棵有K层的满二叉树,让你从根节点开始走(根节点为1),经过K个节点(包括根节点),走到叶子节点,途中经过节点的值,利用加减组成N,并按顺序输出。

我们多试几组数据,我们会发现一个特点,二叉树最左侧的值能够组成所有值,最左侧k-1层的结点之和为sum=(1<<(k-1))-1,sum肯定是一个奇数,如果n为偶数的话,我们第k层的节点选取左侧节点,sum=sum+(1<<(k-1)+1),否则就选取右侧节点,sum=sum+(1<<(k-1))。现在数字已经确定了,就差符号没有确定。

我们知道sum肯定是大于等于n的,sum和n的差值为d,d=sum-n。//因为 sum 和 n 同奇偶,所以d是一个偶数。

n + d = sum    —>    n + d/2 + d/2 = sum   —>  n + d/2 -d/2 = sum - d;

我们找出的 d/2 就是需要减掉的部分,利用二进制的位运算,如果某一位为1就是减号这个数,否则就是加号(二叉树最左侧都是2次幂的数)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int t;
    scanf("%d",&t);
    for(int u=1;u<=t;u++)
    {
        ll n,k,sum;
        scanf("%lld %lld",&n,&k);
        printf("Case #%d:\n",u);
        queue<ll>q;
        for(int i=0;i<k-1;i++)
            q.push(1<<i);       ///先将k-1层的节点值放进队列。
        sum=(1<<k)-1;
        if((sum&1)==(n&1))      ///判断奇偶确定k层节点的值。
            q.push(1<<(k-1));
        else
        {
            sum++;
            q.push((1<<(k-1))+1);
        }
        ll d=(sum-n)>>1;        ///确定加减。
        while(q.size())
        {
            if(d&1) cout<<q.front()<<" -"<<endl;
            else    cout<<q.front()<<" +"<<endl;
            d=d>>1;
            q.pop();
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42211531/article/details/83307122
今日推荐