1028. Hanoi Tower Sequence
Constraints
Time Limit: 1 secs, Memory Limit: 32 MB
Description
Hanoi Tower is a famous game invented by the French mathematician Edourard Lucas in 1883. We are given a tower of n disks, initially stacked in decreasing size on one of three pegs. The objective is to transfer the entire tower to one of the other pegs, moving
only one disk at a time and never moving a larger one onto a smaller.
The best way to tackle this problem is well known: We first transfer the n-1 smallest to a different peg (by recursion), then move the largest, and finally transfer the n-1 smallest back onto the largest. For example, Fig 1 shows the steps of moving 3 disks
from peg 1 to peg 3.
Now we can get a sequence which consists of the red numbers of Fig 1: 1, 2, 1, 3, 1, 2, 1. The ith element of the sequence means the label of the disk that is moved in the ith step. When n = 4, we get a longer sequence: 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1,
2, 1. Obviously, the larger n is, the longer this sequence will be.
Given an integer p, your task is to find out the pth element of this sequence.
Input
The first line of the input file is T, the number of test cases.
Each test case contains one integer p (1<=p<10^100).
Output
Output the pth element of the sequence in a single line. See the sample for the output format.
Print a blank line between the test cases.
Sample Input
4 1 4 100 100000000000000
Sample Output
Case 1: 1 Case 2: 3 Case 3: 3 Case 4: 15
Problem Source
ZSUACM Team Member
不难发现,当p是2^k(k=0,1...)时,输出k+1。仔细观察序列,不断地找到最接近p的比p小的一个2的整数次幂(2^k1),然后得到p与2^k之差。这时分两种情况:
情况1:如果差是也是2的整数次幂(2^k2),则输出k2+1。
情况2:如果差不是2的整数次幂,则以差作为新的p,继续寻找最接近p的比p小的一个2的整数次幂,再做差判断,然后判断是情况1还是情况2。
说的不知道明不明白,任何数都能表达成2^k之和的形式,举个例子,如果p是十进制的14,用二进制表示就是2^3+2^2+2^1。我们只关心最后的2^1,答案是2。用二进制表达就是1110。答案就是最右边0的数量+1。代码如下:
#include <bits/stdc++.h> using namespace std; void divide_2(char *a,int len){ for(int i=len-1;i>=0;i--){ if((a[i]-'0')&1){ a[i+1]+=5; } a[i]=(a[i]-'0')/2+'0'; } } int main(){ int t; scanf("%d",&t); int tmp=t; bool flag=true; while(t--){ char a[200]; scanf("%s",a); int len=strlen(a); int countt=1; while(!(a[len-1]-'0'&1)){ divide_2(a,len); countt++; } if(!flag) printf("\n"); printf("Case %d: %d\n",tmp-t,countt); flag=false; } }