// [7/4/2014 Sjm]
关键:“截断”处理
/*
在此题上花了好久,最后在大牛提醒下才AC,还是要多见题型、多练啊。。。
如果接触字典树,对于此题,大体的思路会有的
1)建立字典树:根据前 100000 斐波那契数
2)根据输入的数字串去字典树中搜索。
需要解决的问题:
1)记录最先到达此处节点的斐波那契数的标号:字典树结构体中加入一个 number 解决
2)两个数字字符串相加(我之前写的一个,过掉之后,翻看其他人代码,发现自己写的又丑又长,果断把方法学过来。。。)
***************************************会遇到的问题**********************************
1)由于计算前 100000 斐波那契数,而实际有用的却只有前 40 位,所以要对所求值做“截断”处理。
也就是说,当所求斐波那契数长度大于50时,截取掉个位,保留不包含个位的高位,这样每次计算
出的值可以保证在50多位。(开数组中可以大一些,若MLE,再减小)
2)存入字典树时,最多存入40位即可。(多一些更保险,但防止MLE)
*************************************************************************************
话说最坑的是把代码中两个变量弄混了,找了好久的 bug 。。。。悲剧啊
。。。不过又见到了一种之前没见过的题型
*/
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX = 10, MAX_LEN = 55;
char t_str[MAX_LEN];
void Str_Add(char str1[], char str2[], char str[]) {
int len1 = strlen(str1) - 1, len2 = strlen(str2) - 1;
int len = 0, to_add = 0;
int pos1, pos2, pos;
while ((len1 >= 0) || (len2 >= 0)) {
if (len1 < 0) pos1 = 0;
else pos1 = str1[len1] - '0';
if (len2 < 0) pos2 = 0;
else pos2 = str2[len2] - '0';
pos = pos1 + pos2 + to_add;
t_str[len++] = pos % 10 + '0';
to_add = pos / 10;
len1--;
len2--;
}
if (to_add > 0) {
t_str[len++] = to_add + '0';
}
for (int i = 0; i < len; i++) {
str[i] = t_str[len - 1 - i];
}
str[len] = '\0';
}
struct Trie {
Trie* next[MAX];
int number;
Trie() {
memset(next, NULL, sizeof(next));
number = -1;
}
};
Trie* Root = new Trie;
void CreTrie(char str[], int num)
{
int len = strlen(str);
Trie* p = Root;
for (int i = 0; i < len && i < 40; i++) {
int pos = str[i] - '0';
if (!p->next[pos]) {
p->next[pos] = new Trie;
}
p = p->next[pos];
if (-1 == p->number) {
p->number = num;
}
}
}
int SeaTrie(char str[])
{
int len = strlen(str);
Trie* p = Root;
for (int i = 0; i < len; i++) {
int pos = str[i] - '0';
if (!p->next[pos]) {
return -1;
}
else {
p = p->next[pos];
}
}
return p->number;
}
void DelTrie(Trie * T) {
for (int i = 0; i < MAX; i++) {
if (T->next[i]) {
DelTrie(T->next[i]);
}
}
delete[] T;
}
void Get_Fib()
{
char str1[MAX_LEN] = "1";
char str2[MAX_LEN] = "1";
char str[MAX_LEN];
CreTrie(str1, 0);
CreTrie(str2, 1);
for (int i = 2; i < 100000; i++) {
int len1 = strlen(str1);
int len2 = strlen(str2);
if (len2 > 50) {
str1[len1 - 1] = 0;
str2[len2 - 1] = 0;
}
Str_Add(str1, str2, str);
CreTrie(str, i);
strcpy(str1, str2);
strcpy(str2, str);
}
}
int main()
{
//freopen("input.txt", "r", stdin);
Get_Fib();
int T;
scanf("%d", &T);
char str[45];
for (int i = 1; i <= T; i++) {
scanf("%s", str);
printf("Case #%d: %d\n", i, SeaTrie(str));
}
DelTrie(Root);
return 0;
}