HDU - 5573 Binary Tree(思维+构造+二进制)
題目鏈接:點擊查看
題目大意:給出一棵無限大的完全二叉樹,每次給出一個 n 和一個 k ,要求從點 1 出發一直向下,找到一條長度為 k 的路徑,對于路徑上的點可以加上其編號,也可以減去其編號,需要構造出一種方案,使得計算的結果為 n
題目分析:因為 k 最大只有 60 ,給足了提示是需要往二進制上思考,但奈何對二進制的題目不太敏感,之前打 cf 時碰到的二進制題目也是因為不會做無奈只能掉分。。菜啊
回到這個題目,稍微畫幾層這個完全二叉樹,不難發現最左邊的一條鏈上恰好是二進制數,也就是 1 , 2 , 4 , 8 ... ,因為題目保證了?,所以最左邊一條鏈之和我們記為 sum,一定有 sum >= n?
所以我們完全可以選擇最左邊的這條鏈,然后在適當的位置將正號變為負號即可,考慮變號的影響,對于一個位置 x ,原本 sum = 1 + 2 + 4 + ... + x + ... + 2^k, 現在如果將 x 前面的正號變為負號,其影響是 1 + 2 + 4 + ... - x + ... + 2^k = sum - 2 * x
可以看到,如果將一個位置的正號變為負號,總的 sum 會減少其兩倍的貢獻,換一種思想,如果我們想要讓 sum 減少 x ( x 為偶數 )的話,那么我們只需要將編號為 x/2 的節點變號即可
接下來我們設置變量 delta = sum - n ,也就是說我們只需要將最左邊的這條鏈,減少 delta 的量,就可以讓其計算的結果等于 n 了,如果 delta 為偶數的話,上文也提到了,直接將其除以 2 ,然后找到相應的位置變號即可
現在考慮如果 delta 為奇數該如何處理,這個時候我們只需要在第 k - 1 層到達第 k 層時,遍歷其右兒子而不是其左兒子就可以了,這樣的話 sum 就變成了 sum + 1,此時再去計算 delta 的話就是偶數了,處理方法同上
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=2e5+100;int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;int kase=0;while(w--){LL n,k;scanf("%lld%lld",&n,&k);LL sum=(1<<k)-1;LL delta=sum-n;bool flag=(delta&1);delta=(delta+1)/2;printf("Case #%d:\n",++kase);for(int i=0;i<k-1;i++){if((delta>>i)&1)printf("%lld -\n",1LL<<i);elseprintf("%lld +\n",1LL<<i);}if(flag)printf("%lld +\n",(1LL<<k-1)+1);elseprintf("%lld +\n",1LL<<k-1);}return 0; }?
總結
以上是生活随笔為你收集整理的HDU - 5573 Binary Tree(思维+构造+二进制)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1252L R
- 下一篇: CodeForces - 1252E S