题目链接:https://vjudge.net/problem/HDU-4099
题意:给T组询问,每个询问为一个字符串(长度<=40),求以该字符串为开始的fibonacci数列的第一个元素的下标,如果在前100000项里都没有,输出-1。
思路:
首先是fibonacci数列这一部分,要用高精度先处理出前1e5项,但显然不能保留每一项的所有位,因为前缀只有40位,我们也只需要计算数列的前40位,为了保证前40位的正确,我计算到了70位。
然后是字典树记录前缀,字典树大概最多40层,空间1e7左右。
AC code:
#include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<cmath> #include<cstring> #include<cstdlib> using namespace std; int compare(string str1,string str2){ int len1=str1.length(),len2=str2.length(); if(len1<len2) return -1; else if(len1>len2) return 1; else return str1.compare(str2); } char c[205]; void add(char *a,char *b,char *back) { int i = (int)strlen(a) - 1,j = (int)strlen(b) - 1; int x = 0,y = 0,z = 0,up = 0,cnt = -1; 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[++cnt] = z % 10 + '0'; up = z / 10; i--;j--; } if(up > 0) c[++cnt] = up + '0'; for(int i = 0;i <= cnt;i++) back[i] = c[cnt - i]; back[++cnt] = '\0'; } const int maxn=1e5+5; const int maxm=1e7+5; string str[3]; char s[50]; int tot,T,cas,cnt,trie[maxm][12],key[maxm]; void insert(char* s,int k){ int len=min((int)strlen(s),43),u=0; for(int i=0;i<len;++i){ int t=s[i]-'0'; if(!trie[u][t]){ ++cnt; key[cnt]=k; trie[u][t]=cnt; } u=trie[u][t]; } } int query(char *s){ int len=strlen(s),u=0; for(int i=0;i<len;++i){ int t=s[i]-'0'; if(!trie[u][t]) return -1; u=trie[u][t]; } return key[u]; } void init() { tot = 1; char a[205],b[205],ans[205]; a[0] = b[0] = '1';a[1] = b[1] = 0; insert(b,0); for(int i = 2;i < 100000;++i) { if(strlen(b) > 70) { b[strlen(b) - 1] = 0; a[strlen(a) - 1] = 0; } add(a,b,ans); insert(ans,i); strcpy(a,b); strcpy(b,ans); } } int main(){ init(); scanf("%d",&T); while(T--){ scanf("%s",s); printf("Case #%d: %d\n",++cas,query(s)); } return 0; }