ZOJ1633-Big String(递归与分治)

目录

问题描述

输入

输出

输入样例

输出样例

算法分析

1.从字符串的长度研究字符串生成规律

2.算法优化


问题描述

设A=“^__^”(4个字符),B=“T.T”(三个字符),然后以AB为基础,构造无限长的字符串,重复规则如下:

(1)把A接在B的后面构成新的字符串C。例如,A=“^__^”,B=“T.T”,则C=BA=“T.T^__^”。

(2)令A=B,B=C,如上例所示,则A=“T.T”,B=“T.T^__^”。

编程任务:给出此无限长字符串中的第n个字符。

输入

输入有多组测试例。每个测试例只有一个整数N,其中(1\leq N\leq 2^{63}-1)

输出

对每个测试例输出一行,是此无限长字符串中的第N个字符(序号从1开始).

输入样例

1

2

4

8

输出样例

T

.

^

T

算法分析

本题看起来很简单,字符串的组合也很有规律,有的读者就试图研究叠加后的字符串规律。结果发现,叠加后的字符串虽然有规律,但是与输入的数据n之间没有直接的联系。

1.从字符串的长度研究字符串生成规律

a=strlen("^__^")        ->a=4

b=strlen("T.T")          ->b=3

c=strlen("T.T^__^")   ->c=7

再按照题目给定的步骤重复,就很容易发现,这正是以a,b为基数的斐波那契(Fibonacci)数列。

对于输入的正整数n,它位于经过若干次按斐波那契数列的规律叠加后的字符串中。无论它如何叠加,该位置的字符总是在字符串C中。本题就变成给定一个正整数n,求出小于n的最大斐波那契数,n与该斐波那契数的差正是该字符在字符串C中的位置。

输出时要注意,字符串的位置是从0开始编号的,所以用这个差值当下标时需要减去1。

2.算法优化

由于n最大可达2^{63}-1,对于输入的每个n,都去计算小于n的最大斐波那契数,显然是非常浪费时间的。解决的办法是预先把在2^{63}-1 范围内的所有斐波那契数求出来,放到一个数组中。经过测算,该斐波那契数列最多为86项,第86项的斐波那契数约是6.02\times 10^{18},而2^{63}-1约是9.22\times 10^{18},如下所示。

算法:

#define LEN 88
string base=="T.T^__^";
//将斐波那契(Fibonacci)数列在2^63-1范围之内的数全部计算出来
long long int f[LEN];
f[0] = 7;f[1] = 10;
for(int i = 2;i < LEN;i++)
   f[i] = f[i-1] + f[i-2];
long long int n;
while(cin>>n)
{
     //对于每一个n,减去小于n的最大斐波那契数
      while(n > 7)
      {
         int i=0;
         while(i < LEN&& f[i] < n)
             i++;
           n-=f[i-1];
      }
     //n中剩下的值,就是该字符在base中的位置
     cout<<base[n-1]<<endl;
}

转载地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1633

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值