UVA 12333 Revenge of Fibonacci

题目描述

Description

The well-known Fibonacci sequence is defined as following:

F(0) = F(1) = 1
F(n) = F(n − 1) + F(n − 2) ∀n ≥ 2

Here we regard n as the index of the Fibonacci number F(n).

This sequence has been studied since the publication of Fibonacci’s book Liber Abaci. So far, many properties of this sequence have been introduced.

You had been interested in this sequence, while after reading lots of papers about it. You think there’s no need to research in it anymore because of the lack of its unrevealed properties. Yesterday, you decided to study some other sequences like Lucas sequence instead.

Fibonacci came into your dream last night. “Stupid human beings. Lots of important properties of Fibonacci sequence have not been studied by anyone, for example, from the Fibonacci number 347746739…”

You woke up and couldn’t remember the whole number except the first few digits Fibonacci told you. You decided to write a program to find this number out in order to continue your research on Fibonacci sequence.

Input

There are multiple test cases. The first line of input contains a single integer T denoting the number of test cases (T ≤ 50000).

For each test case, there is a single line containing one non-empty string made up of at most 40 digits. And there won’t be any unnecessary leading zeroes.

Output

For each test case, output the smallest index of the smallest Fibonacci number whose decimal notation begins with the given digits. If no Fibonacci number with index smaller than 100000 satisfy that condition, output ‘-1’ instead — you think what Fibonacci wants to told you beyonds your ability.

Sample Input

15
1
12
123
1234
12345
9
98
987
9876
98765
89
32
51075176167176176176
347746739
5610

Sample Output

Case #1: 0
Case #2: 25
Case #3: 226
Case #4: 1628
Case #5: 49516
Case #6: 15
Case #7: 15
Case #8: 15
Case #9: 43764
Case #10: 49750
Case #11: 10
Case #12: 51
Case #13: -1
Case #14: 1233
Case #15: 22374

题目链接

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3755

解题思路

其实这是一道非常水的题,就是一个简单的字典树模板题。

题意是输入一个不超过40位数字的数n,然后找出前缀为n的最小的斐波那契数的下标是多少。

用C++做的话需要手写大数加法,然后算出100000项的斐波那契数,统统存到字典树里,存的时候增加一个参数,记录当前存的斐波那契数的下标。但是后面算出来的斐波那契数的位数非常的多,计算的时候肯定会超时,存储的时候也肯定会爆内存。所以需要截断一下,只计算前50位就可以了。

一开始本来使用C++写的,但是不知为何一直RE(在自己电脑上就爆内存了),后来一气之下改用Java,处理一下大数和输入输出,就把这题过了。

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import java.io.*;
import java.math.*;
import java.util.*;

public class Main
{
static int[][] ch = new int[5000005][10];
static int[] val = new int[5000005];
static int cnt;
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
String str;
int t;
Fib();
t = s.nextInt();
for (int i = 1; i <= t; i++)
{
str = s.next();
System.out.printf("Case #%d: %d\n", i, query(str));
}
}

static void Fib()
{
cnt = 1;
String a, b;
BigInteger x = BigInteger.ONE, y = BigInteger.ONE, ret;
insert("1", 0);
for (int i = 2; i < 100000; i++)
{
a = x.toString();
b = y.toString();
if (b.length() > 50)
{
x = new BigInteger(a.substring(0, a.length() - 1));
y = new BigInteger(b.substring(0, b.length() - 1));
}
ret = x.add(y);
insert(ret.toString(), i);
x = y;
y = ret;
}
}

static void insert(String s, int x)
{
int u = 0;
for (int i = 0; i < s.length() && i < 50; i++)
{
int k = s.charAt(i) - '0';
if (ch[u][k] == 0)
{
val[cnt] = x;
ch[u][k] = cnt++;
}
u = ch[u][k];
}
}

static int query(String s)
{
int u = 0;
for (int i = 0; i < s.length(); i++)
{
int k = s.charAt(i) - '0';
if (ch[u][k] == 0) return -1;
u = ch[u][k];
}
return val[u];
}
}