hdu 5573 Binary Tree(2015年ICPC上海 B題)(二進制位運算,思維規律題)*

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5573Binary Tree

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2172 Accepted Submission(s): 1294
Special Judge

Problem Description
The Old Frog King lives on the root of an infinite tree. According to the law, each node should connect to exactly two nodes on the next level, forming a full binary tree.

Since the king is professional in math, he sets a number to each node. Specifically, the root of the tree, where the King lives, is 1. Say froot=1.

And for each node u, labels as fu, the left child is fu×2 and right child is fu×2+1. The king looks at his tree kingdom, and feels satisfied.

Time flies, and the frog king gets sick. According to the old dark magic, there is a way for the king to live for another N years, only if he could collect exactly N soul gems.

Initially the king has zero soul gems, and he is now at the root. He will walk down, choosing left or right child to continue. Each time at node x, the number at the node is fx (remember froot=1), he can choose to increase his number of soul gem by fx, or decrease it by fx.

He will walk from the root, visit exactly K nodes (including the root), and do the increasement or decreasement as told. If at last the number is N, then he will succeed.

Noting as the soul gem is some kind of magic, the number of soul gems the king has could be negative.

Given N, K, help the King find a way to collect exactly N soul gems by visiting exactly K nodes.

Input
First line contains an integer T, which indicates the number of test cases.

Every test case contains two integers N and K, which indicates soul gems the frog king want to collect and number of nodes he can visit.

⋅ 1≤T≤100.

⋅ 1≤N≤109.

⋅ N≤2K≤260.

Output
For every test case, you should output “Case #x:” first, where x indicates the case number and counts from 1.

Then K lines follows, each line is formated as ‘a b’, where a is node label of the node the frog visited, and b is either ‘+’ or ‘-’ which means he increases / decreases his number by a.

It’s guaranteed that there are at least one solution and if there are more than one solutions, you can output any of them.

Sample Input

2
5 3
10 4

Sample Output

Case #1:
1 +
3 -
7 +
Case #2:
1 +
3 +
6 -
12 +


這種與二叉樹有關的有可能與數的二進制表示有關係

在我拼命畫樹的時候,隊友的發現了個大規律,題目中的N<=2^k,那麼 在第K層的最左邊的兩個結點,可以表示所有的N,並且1~K-1層的路徑都是一樣的,這兩個結點就是2K12^{K-1}2K1+12^{K-1}+1,對於2K12^{K-1}這個結點可以表示前2K12^{K-1}個奇數,而2K1+12^{K-1}+1結點可以表示前2K12^{K-1}個偶數(最大的這個偶數恰好等於2K2^K
在這裏插入圖片描述
因此對於奇數N只要計算出終點爲2K12^{K-1}結點的路徑上的每個節點的加減,那麼對於偶數N+1 在1~K-1層的路徑是相同的並且每個結點的加減情況也相同,只是在路徑的終點由2K12^{K-1}變成2K1+12^{K-1}+1,因此就有N變成了N+1.因此下面只對2K12^{K-1}結點進行分析
以K=5爲例,終點結點爲16,對N=1,3,5,7,9,11,13,15,···,31.

二進制 1 2 4 8 16
N=1 - - - - +
N=3 + - - - +
N=5 - + - - +
N=7 + + - - +
N=9 - - + - +
N=11 + - + - +
N=13 - + + - +
N=15 + + + - +
\dots

發現,每增加2,就是從左往右找到第一個’-'號,改爲‘+’號,找到後將左邊的‘+’號都改爲‘-’號
對於N=15,在N=1的基礎上加了7個2,而之前的加2操作與二進制有些類似,N=15的前三個‘+’號就是7的二進制表示形式,N=13前面的“-++”也是6的二進制表示,把上面表格中的+號用1表示,-號用0表示,就更加明瞭

對於N=2,K=1的情況,好像是無解的

代碼:

#include <bits/stdc++.h>

using namespace std;
#define ll long long 


int main()
{
	int t;
	int a,b;
	scanf("%d",&t);
	for(int cas = 1;cas<=t;cas++)
	{
		scanf("%d%d",&a,&b);
		printf("Case #%d:\n",cas);
		int flag=1;
		int tm;
		ll bs=1;
		if(a&1) {flag=0;tm=a/2;}
		else tm=(a-1)/2;
		for(int i=1;i<b;i++)
		{
			if(tm==0)
			{
				printf("%lld -\n",bs);
			}
			else if(tm&1)
			{
				printf("%lld +\n",bs);
			}
			else
			{
				printf("%lld -\n",bs);
			}
			bs=bs<<1;
			if(tm) tm>>=1;
		}
		
		
		printf("%lld +\n",bs+flag);
		
		
	}
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章