1. 程式人生 > >HDU5573-Binary Tree(思維)

HDU5573-Binary Tree(思維)

題目意思:

你是一隻青蛙,你在一個無窮大的二叉樹上,按照線段樹那種標號方式就像下面這個一樣。

1234567

上圖只是意思一樣,這個二叉樹是無窮大的,每個節點你可以得到標號數量的續命寶石或者失去該數量的續命寶石。你要從第1層走到第k層,走k步,對於每個節點你可以選擇得到這個數量的續命寶石或者失去,要使得最後的寶石數量恰好為n,保證答案一定存在,輸入方案。

題目思路:

我們把上圖的標號二進位制化

100101110111001010011

我們可以只取001,010,100,也就是2的冪次。 因為恰好取走k層,所以我們可以先把前k層都取了那麼取到(11111)2=2k1(11\ldots 111)_2 = 2^{k}-1

。 又因為我們使得最後的續命寶石敲好為n個,所以我們需要捨棄掉t=2k1nt=2^{k}-1 - n個寶石,那麼我們可以根據t的二進位制選擇捨棄哪些層數對應標號的寶石。 但是這裡注意一個問題,我們一開始假設都取了,現在每捨棄一層,相當於失去兩倍的該層標號的寶石,說白了,我們失去寶石數量只能是偶數,如果t是奇數,我們則應該在最後一層選擇2^(k-1) + 1,這樣我們丟失的數量就變成了偶數(這裡特殊處理)

程式碼:

#include<bits/stdc++.h>
using namespace std;
long long a[64][
2],b[64][2]; int main(){ a[0][0]=b[0][0]=1; for(int i=1;i<=60;i++){ a[i][0]=a[i-1][0]*2; a[i][1]=a[i][0]+1; } for(int i=1;i<=60;i++){ b[i][0]=a[i][0]+b[i-1][0]; b[i][1]=b[i][0]+1; } int T,ca=0; cin>>T; long long n,k,t; vector<pair<
long long,int> >ans; while(T--){ cin>>n>>k; cout<<"Case #"<<++ca<<": "<<endl; ans.clear(); if(n&1){ t=b[k-1][0]-n; for(int i=0;i<k;i++) ans.push_back(make_pair(a[i][0],0)); } else{ t=b[k-1][1]-n; for(int i=0;i<k-1;i++) ans.push_back(make_pair(a[i][0],0)); ans.push_back(make_pair(a[k-1][1],0)); } int ct=0; t/=2; while(t){ if(t&1){ ans[ct].second=1; } t/=2; ct++; } for(int i=0;i<ans.size();i++){ cout<<ans[i].first<<' '; if(ans[i].second==0) cout<<'+'<<endl; else cout<<'-'<<endl; } } return 0; }