Sicily 1028 Hanoi Tower Sequence

来源:互联网 发布:苹果mac快捷键删除 编辑:程序博客网 时间:2024/05/22 09:42

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

观察移动的汉诺塔块的序列,可以发现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


原创粉丝点击