openjudge9269:Big String超级字符串 详解

9269:Big String超级字符串

查看 提交 统计 提问
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 131072kB
描述

fish在无数次oi竞赛的狱炼之后,悟出一个真理,往往越容易的题目,陷阱越深。由此,fish创作了这道题目。 
fish首先给出两个短串A=’4567’ (4个字符), B=’123’(3个字符)。反复进行如下的操作得到一个长串C。 
(1)C=B+A (例如:A=’4567’ ,B=’123’ C=B+A=’1234567’) 
(2)A=B B=C (上述例子 A=’123’ B=’1234567’) 
请你编程找出这个长串的第n个字符。 

输入

第一行包含一个整数 n (1<=n<=10^9)

输出

仅一行,包含一个字符,表示这个长串的第n个字符。

样例输入
9
样例输出
2































显然这数据范围是很尴尬的=。=,在纸上模拟一下:

A0=4567  B0=123  -> C1=1234567

 A1=B0=123  B1=C1=1234567      ->C2=A1+B1=1234567123 

A2=B1=C1=1234567 B2=C2=1234567123  ->C3=A2+B2=C1+C2=12345671234567123

A3=B2=C2=1234567123  B3=C3=12345671234567123 -> C4=A3+B3=C2+C3

........

其实应该已经发现规律了:

(1)C[i]=C[i-1]+C[i-2](i>=3)

(2)每一位我们都可以在1234567这个字串中找到

(3)每一个新子串都可以看做是1234567或它的子串组成的


那么我们只需要知道第n位是1234567 中的第几位,而对这个那么长的子串究竟是什么根本没用=。=

所以我们根本没必要存具体的子串只需要存它一共有几位就行了

即:f[i]=f[i-1]+f[i-2](i>=3)

       f[1]=3;f[2]=7


所以我们只需要知道第n位是在什么时候产生的就行了,

比如说第16位,由于16>10 并且16<17 所以它是在产生到第17位的时候才知道的,

那么我们对前10位完全不感兴趣,直接16-10=6,因为它是在组成该大子串的第二个小子串中,

那么同理我们只需要知道第二个小子串中的第6位是在1234567中的第几位

.......

一直推下去一直到n<=7,即可以确定它是在1234567中的具体的位置

输出该位的数字(字符)即可

var
        f               :array[0..45] of int64;
        n               :int64;
        i               :longint;
        s               :string;
begin
   read(n);s:='1234567';
   f[1]:=3;f[2]:=7;
   for i:=3 to 42 do f[i]:=f[i-1]+f[i-2];
    for i:=1 to 42 do
     if (n<=f[i+1]) and (n>f[i]) then break;

   //
   while (n>7) and (i>=1) do
   begin
      while (n<=f[i]) and (i>=1) do dec(i);
      dec(n,f[i]);
   end;
   writeln(s[n]);
end.
——by Eirlys

转载请注明出处=w=
openjudge9269:Big String超级字符串 详解_第1张图片

你可能感兴趣的:(openjudge9269:Big String超级字符串 详解)