Sicily 1028 Hanoi Tower Sequence

    汉诺塔问题,最经典的解法是递归,但是这道题的数据太大,没有办法实现。实际上这道题要求的是找出某一位置的汉诺块,没有必要完全模拟,而是要找出特定的汉诺塔会出现在哪些位置。

观察移动的汉诺塔块的序列,可以发现n第一次出现的序列号为2^(n-1)次方。这可以由汉诺塔的归纳办法归纳证明(递归式为f(n)=f(n-1), n, f(n-1),证明略)。又由递归式可以知道,汉诺再次出现是f(n+1)等式右边两个f(n)的后一个,递归示意图如下:


可由对称性求出n第二次出现的序列号为(2^(n+1)-1)-(2^(n-1)-1)=3*2^(n-1);

再考虑f(n+2),可求出第三次,第四次出现为5*2^(n-1), 7*2^(n-1),依此类推,可知n出现的位置为2^(n-1)次方的奇数倍,这在二进制中表现为倒数第n位为第一个1的所有数。于是该题转化为高精度二进制转化的问题。

#include <iostream>
#include <string>

using namespace std;

pair<string, int> divide(string dividend, int divisor) {
	string quotient;
	int remainder=0;
	for (string::iterator iter=dividend.begin(); iter!=dividend.end(); iter++) {
		int tmp=remainder*10+((*iter)-'0');
		quotient+=(tmp/divisor+'0');
		remainder=tmp%divisor;
	}
	return make_pair(quotient, remainder);
}

string decimal2InverseBinary(string d) {
	string b;

	while(!d.empty()) {
		b+=(divide(d, 2).second+'0');
		d=divide(d, 2).first;
		if(d[0]=='0')
			d.erase(d.begin());
	}

	return b;
}

int main() {
	int cases;
	cin>>cases;
	int counter=0;
	while(counter++<cases) {
		string p;
		cin>>p;
		int n=decimal2InverseBinary(p).find('1')+1;
		cout<<"Case "<<counter<<": "<<n<<"\n";
		if (counter!=cases)
			cout<<"\n";
	}

	return 0;
}

// by wbchou
// Feb 17th, 2012


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值