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 }
时间: 2024-11-03 03:27:20