sicily 1028. Hanoi Tower Sequence

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;	
	}
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值