题意:给出斐波那契数列的前k位,k不超过40,找出最小的正整数n,满足F(n)的前k位与给定数的前k位相同,斐波那契数列的项数不超过100000。
解析:本题可以分为两步:
第一步就是预处理出100000项斐波那契数列的前40位,插入到字典树中。
第二步就是查询匹配求最小的n。
对于第一步,我们可以把斐波那契数列精确到50多位,然后只存40位即可,这样就防止进位的误差。在斐波那契数列加法过程中,我们只把它的前50多
位进行相加,不然存不下。
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; const int N=10; int f1[65],f2[65],f3[65]; class Trie { public: int v; int flag; Trie *next[N]; Trie() { v=-1; memset(next,NULL,sizeof(next)); } }; Trie *root; void Insert(char *S,int ans) { int len=strlen(S); Trie *p=root; for(int i=0;i<len;i++) { int id=S[i]-'0'; if(p->next[id]==NULL) p->next[id]=new Trie(); p=p->next[id]; if(p->v<0) p->v=ans; } } int Find(char *S) { Trie *p=root; int count; int len=strlen(S); for(int i=0;i<len;i++) { int id=S[i]-'0'; p=p->next[id]; if(p==NULL) return -1; else count=p->v; } return count; } void Init() { int h; char str[65]="1"; memset(f1,0,sizeof(f1)); memset(f2,0,sizeof(f2)); memset(f3,0,sizeof(f3)); f1[0]=1;f2[0]=1; Insert(str,0); for(int i=2;i<100000;i++) { memset(str,0,sizeof(str)); int r=0; for(int j=0;j<60;j++) { f3[j]=f1[j]+f2[j]+r; r=f3[j]/10; f3[j]%=10; } for(int j=59;j>=0;j--) if(f3[j]) { h=j; break; } int k=0; for(int j=h;j>=0;j--) { str[k++]=f3[j]+'0'; if(k>=40) break; } Insert(str,i); if(h>55) { for(int j=1;j<59;j++) f3[j-1]=f3[j]; for(int j=1;j<59;j++) f2[j-1]=f2[j]; } for(int j=0;j<60;j++) f1[j]=f2[j]; for(int j=0;j<60;j++) f2[j]=f3[j]; } } int main() { root=new Trie(); Init(); char str[105]; int t,i,j,k=1; scanf("%d",&t); while(t--) { scanf("%s",str); printf("Case #%d: ",k++); int tmp=Find(str); printf("%d ",tmp); } return 0; }