hdu5573 二叉树找规律,二进制相关

时间:2021-11-19 02:34:14

input

T 1<=T<=100

n k  1<=n<=1e9  n<=2^k<=2^60

output

从1走到第k层,下一层的数是上一层的数×2或者×2+1,每次加上或者减去走过的数得到n

输出每行输出这一层的数,再输出加还是减

做法:可以发现每次都往×2走时e可以得到<2^k的所有奇数,然后a将最后一个改为2^k+1就可以在原来的基础上得到所有偶数

如用1,2,4,8通过加减可以得到-1,1,-3,3,-5,5,-7,7,然后1,2,4,9通过加减就可以得到-2,2,-4,4,-6,6,-8,8

然后根据n的二进制就可以确定加还是减,如4层时n的二进制是0011,因为是正数,第一位必为+,再找到第一个是一的,一直减到这一位即可,即8-4-2+1

 #include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
#define MAX 100000
#define LL long long
using namespace std;
int a[],n,m,k,cas=,T;
int main()
{
//freopen("/home/user/桌面/in","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&m,&k);
printf("Case #%d:\n",cas++);
n=m&?m:m-;
int c=;
memset(a,,sizeof(a));
while(n)
{
a[++c]=n&;
n>>=;
}
for(int i=k,idx;i>;i--)
{
idx=i;
while(i>&&!a[i])//找到为1的那一位
{
i--;
}
//printf("i:%d idx:%d\n",i,idx);
if(i<=) break;
if(a[i]&&i!=idx) swap(a[i],a[idx]);
}
for(int i=;i<k;i++) printf("%lld %c\n",1LL<<(i-),a[i]?'+':'-');
printf("%lld %c\n",1LL<<(k-)|(!(m&)),a[k]?'+':'-');
// LL sum=0;for(int i=1;i<=k;i++) sum+=(1LL<<(i-1))*(a[i]?1:-1);
// if(!(m&1)) sum++;printf("%lld\n",sum);
}
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return ;
}