2015上海現場賽 HDU 5573
阿新 • • 發佈:2018-11-15
這是一道在克隆賽碰到的題,當時看題隊友以為是樹形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; }