题意:输入一个数,这个数是斐波那契数列的前缀,求满足这个前缀的最小的下标。给出的数不超过40位,若满足这个前缀的最小下标超过100000则输出-1。
思路:将斐波那契的前缀放到字典树中,由于两数相加有可能会进位,我们把斐波那契的前60位放到字典树中,这样就不会因为进位而产生误差。
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; char str[3][100]; char temp[100]; struct Trie { Trie *next[10]; int v; void init() { v = -1; for(int i = 0; i < 10; i++) next[i] = NULL; } }*root; void insert(char *s,int val) { int n = strlen(s); Trie *p = root,*q; for(int i = 0; i < n && i<41; i++) { int id = s[i]-'0'; if(p->next[id]==NULL) { q = new Trie(); q->init(); p->next[id] = q; } p = p->next[id]; if(p->v<0) p->v = val; } } int find(char *s) { int n = strlen(s); Trie *p = root; for(int i = 0; i < n; i++) { int id = s[i]-'0'; if(p->next[id]==NULL) return -1; p = p->next[id]; } return p->v; } void add(char *a,char *b,char *c) { int len1 = strlen(a); int len2 = strlen(b); int i = len1-1,j = len2-1; int k = 0; int p = 0; while(i>=0||j>=0) { int x,y,z; if(i<0) x = 0; else x = a[i]-'0'; if(j<0) y = 0; else y = b[j]-'0'; z = x+y+p; temp[k++] = z%10+'0'; p = z/10; i--; j--; } if(p) temp[k++] = p+'0'; for(int i = 0; i < k; i++) c[i] = temp[k-i-1]; c[k] = 0; } int main() { root = (Trie*)malloc(sizeof(Trie)); root->init(); str[0][0] = '1'; str[0][1] = 0; insert(str[0],0); str[1][0] = '1'; str[1][1] = 0; for(int i = 2; i < 100000; i++) { int len1 = strlen(str[0]); int len2 = strlen(str[1]); if(len2>60) { str[0][len1-1] = 0; str[1][len2-1] = 0; } add(str[0],str[1],str[2]); insert(str[2],i); strcpy(str[0],str[1]); strcpy(str[1],str[2]); } int T; int kase = 0; cin >> T; while(T--) { kase++; char s[100]; cin >> s; int ans = find(s); cout<<"Case #"<<kase<<": "<<ans<<endl; } return 0; }