只看前40位前缀,将前10W个斐波那契数存入Trie树,超过40位的就只存前40位前缀,对最先到达的前缀进行唯一标记就行了,然后搜索。思路是看别人的,代码有参考,这题有待继续的更好的方法,,这里先放上A过的代码。
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#define MAX 10
//const int MAX=10;
typedef struct Node{
int isStr;
struct Node *next[MAX];
Node():isStr(-1){
memset(next, NULL, sizeof(next));
}
~Node(){
for(int i = 0;i < MAX; ++i)
if(next[i] != NULL)
delete next[i];
}
}TrieNode,*Trie;
Trie root;
char c[100];
void add(char a[],char b[],char back[]){
int i,j,k;
int x,y,z;
int up;
i=strlen(a)-1;
j=strlen(b)-1;
k=0;
up=0;
while(i>=0||j>=0){
if(i<0)x=0;
else x=a[i]-'0';
if(j<0)y=0;
else y=b[j]-'0';
z=x+y+up;
c[k++]=z%10+'0';
up=z/10;
i--;
j--;
}
if(up>0)c[k++]=up+'0';
for(i=0;i<k;i++)back[i]=c[k-1-i];
back[k]='\0';
}
void Insert(char *s,int index){
TrieNode *p = root;
int num = 0;
while(*s && num < 41){//只管前40位
if(p ->next[*s-'0'] == NULL){
p ->next[*s-'0'] = new TrieNode;
}
p = p ->next[*s-'0'];
if(p->isStr < 0) p->isStr = index;//保留前缀最先到达这里的斐波那契数最小的那个数的编号
s++;
num ++;
}
return ;
}
int find(char *s){
TrieNode *p = root;
int count;
while(*s){
if(p->next[*s - '0'] != NULL){
p = p->next[*s - '0'];
count = p->isStr;
s++;
}
else return -1;
}
return count;
}
char str[3][100];
int main() {
//freopen("f:\\in1.txt","r",stdin);
//freopen("f:\\out1.txt","w",stdout);
int i, Case;
char str1[60];
root = new TrieNode;
str[0][0]='1';
str[0][1]=0;
Insert(str[0],0);
str[1][0]='1';
str[1][1]=0;
Insert(str[1],1);
for(int i=2;i<100000;i++){
int len1=strlen(str[0]);
int len2=strlen(str[1]);
if(len2>60){
str[1][len2-1]=0;
str[0][len1-1]=0;
}
add(str[0],str[1],str[2]);
Insert(str[2],i);
strcpy(str[0],str[1]);
strcpy(str[1],str[2]);
}
scanf("%d",&Case);
for(i = 1; i <= Case; i++){
scanf("%s",str1);
printf("Case #%d: %d\n",i,find(str1));
}
delete root;
}