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 11. Say froot=1froot=1.
And for each node uu, labels as fufu, the left child is fu×2fu×2 and right child is fu×2+1fu×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 NN years, only if he could collect exactly NN 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 xx, the number at the node is fxfx (remember froot=1froot=1), he can choose to increase his number of soul gem by fxfx, or decrease it by fxfx.
He will walk from the root, visit exactly KK nodes (including the root), and do the increasement or decreasement as told. If at last the number is NN, 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 NN, KK, help the King find a way to collect exactly NN soul gems by visiting exactly KK nodes.
Input
First line contains an integer TT, which indicates the number of test cases.
Every test case contains two integers NN and KK, which indicates soul gems the frog king want to collect and number of nodes he can visit.
⋅⋅ 1≤T≤1001≤T≤100.
⋅⋅ 1≤N≤1091≤N≤109.
⋅⋅ N≤2K≤260N≤2K≤260.
Output
For every test case, you should output " Case #x:" first, where xx indicates the case number and counts from 11.
Then KK lines follows, each line is formated as ‘a b’, where aa is node label of the node the frog visited, and bb is either ‘+’ or ‘-’ which means he increases / decreases his number by aa.
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 +
题意:有一棵满二叉树,根结点值为1,左子结点为2∗i2∗i,右子结点为2∗i+12∗i+1,给出n和k,求在二叉树上从根向下共走k步,每步可以为当前结点权值取正号或者负号,求一种使最终取值和为n的方案。
我们如果只依靠最左边这一列的加减法,只能表示所有的奇数,来思考一下,1,2,4,8,16,,,从1开始加或者减:<1> 1+偶=奇数;<2> 1-偶=奇数;<3> -1+偶=奇数;<4> -1-偶=奇数;
所以,如果想表示偶数,只需要将最后一位从左子树换为右子树即可;
则对于任意一个正整数,只需要将其二进制上为1的全部取正数,为0的全部不取即可;但是我们的每一个子节点不允许空手而过,必须对每一个节点取正或者取负,那该怎么办,把我不应该取的取负,整体就变小了,把我不应该取的取正,整体就变大了,那就让他们自相残杀,刚好最终等于0就好了【是指那些本不应该取的二进制位上对应的值】;
即,将所有的最左边的节点先全部相加,取和,找出比要取的值多出了多少,除以2,将这“一半”的二进制表示对应的点取负,即用所有节点的和里面的剩余另一半减去,得到最终结果。【偶数将总和先加1变成奇数,即最后的节点换为右节点】
例:
k=4的话,sum=1+2+4+8=2^4-1=15。
n=3:d=sum-n=12,x=d/2=12/2=6,那么我们用20,21,22,…,2(k-2)构造出6来就可以了,即选2和4,那么把2和4取负,其他的全正即可:3=1-2-4+8。
n=6:此时按上面的方法算出来的d=sum-n肯定不是偶数,为了能得到偶数,则sum应该变成sum=1+2+4+9=16.(即在最后一步向右,不走8,而走9),此时d=sum-n=16-6=10,
x=d/2=10/2=5.那么我们用20,21,22,…,2(k-2)构造出5来就可以了,即选1和4,那么把1和4取负,其他的全正即可:6=-1+2-4+9。
实现代码:
#include"cstdio"
#include"cmath"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;
#define Maxn 100
long long a[Maxn],b[Maxn],c[Maxn],d[Maxn];
char x[Maxn];
long long n,k;
int main()
{
int T;
scanf("%d",&T);
a[1]=1;
for(int i=2;i<=61;i++)
{
a[i]=a[i-1]*2;
}
int num=1;
while(T--)
{
scanf("%lld %lld",&n,&k);
for(int i=1;i<=k;i++)
{
b[i]=a[i];
c[i]=1;
}
long long m=a[k+1]-1-n;
if(n%2==0)
{
b[k]++;
m++;
}
long long l=m/2,cnt=0;
for(int i=l;l>0;)
{
d[cnt++]=l%2;
l/=2;
}
for(int i=1,j=0;j<cnt;j++)
{
if(d[j]==1)
{
c[i]=0;
}
i++;
}
for(int i=1;i<=k;i++)
{
if(c[i]==1)
{
x[i] = '+';
}
else
{
x[i] = '-';
}
}
printf("Case #%d:\n",num);
for(int i=1;i<=k;i++)
{
printf("%d %c\n",b[i],x[i]);
}
num++;
}
return 0;
}