We will construct an infinitely long string from two short strings: A = "^__^" (four characters), and B = "T.T" (three characters). Repeat the following steps:
- Concatenate A after B to obtain a new string C. For example, if A = "^__^" and B = "T.T", then C = BA = "T.T^__^".
- Let A = B, B = C -- as the example above A = "T.T", B = "T.T^__^".
Your task is to find out the n-th character of this infinite string.
Input
The input contains multiple test cases, each contains only one integer N (1 <= N <= 2^63 - 1). Proceed to the end of file.
Output
For each test case, print one character on each line, which is the N-th (index begins with 1) character of this infinite string.
Sample Input
1 2 4 8
Sample Output
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中的位置。
输出时要注意,string类型的字符串的位置是从0开始编号的,所以用这个差值当下标时需要减去1。
(2)算法优化
由于n最大可达2^63-1,对于输入的个n,都去计算小于n的最大斐波那契数,显然是非常浪费时间的。解决的办法是预先把在1到2^63-1范围内的所有斐波那契数求出来,放到一个数组中,经过计算,该斐波那契数列最多为86项,第86项的斐波那契数列最多约是6.02*10^18,而2^63-1约是9.22*10^18。
题意:设A="^__^"(4个字符),B="T,T"(3个字符),然后以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个字符。
附上代码:
1 #include <iostream> 2 #include <cstdio> 3 #define len 88 4 using namespace std; 5 int main() 6 { 7 char base[]="T.T^__^"; 8 //将斐波那契数列在2^63-1范围之内的数全部计算出来 9 long long int f[len]; 10 f[0]=7; 11 f[1]=10; 12 for(int i=2; i<len; i++) 13 f[i]=f[i-1]+f[i-2]; 14 long long int n; 15 while(~scanf("%lld",&n)) 16 { 17 //对于每一个n,减去小于n的最大斐波那契数 18 while(n>7) 19 { 20 int i=0; 21 while(i<len&&f[i]<n) 22 i++; 23 n-=f[i-1]; 24 } 25 //n中剩下的值,就是该字符在base中的位置 26 printf("%c ",base[n-1]); 27 } 28 return 0; 29 }