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

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

 1 #include <cstdio>
 2 #include <queue>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <map>
 9 #include <set>
10 #include <ctime>
11 #include <cmath>
12 #include <cctype>
13 #define MAX 100000
14 #define LL long long
15 using namespace std;
16 int a[70],n,m,k,cas=1,T;
17 int main()
18 {
19     //freopen("/home/user/桌面/in","r",stdin);
20     scanf("%d",&T);
21     while(T--)
22     {
23         scanf("%d%d",&m,&k);
24         printf("Case #%d:\n",cas++);
25         n=m&1?m:m-1;
26         int c=0;
27         memset(a,0,sizeof(a));
28         while(n)
29         {
30             a[++c]=n&1;
31             n>>=1;
32         }
33         for(int i=k,idx;i>0;i--)
34         {
35             idx=i;
36             while(i>0&&!a[i])//找到为1的那一位
37             {
38                 i--;
39             }
40             //printf("i:%d idx:%d\n",i,idx);
41             if(i<=0) break;
42             if(a[i]&&i!=idx) swap(a[i],a[idx]);
43         }
44         for(int i=1;i<k;i++) printf("%lld %c\n",1LL<<(i-1),a[i]?'+':'-');
45         printf("%lld %c\n",1LL<<(k-1)|(!(m&1)),a[k]?'+':'-');
46     //    LL sum=0;for(int i=1;i<=k;i++) sum+=(1LL<<(i-1))*(a[i]?1:-1);
47     //    if(!(m&1)) sum++;printf("%lld\n",sum);
48     }
49     //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
50     return 0;
51 }
View Code

 

posted @ 2015-12-18 14:25  cdongyang  阅读(774)  评论(0编辑  收藏  举报