15 1 12 123 1234 12345 9 98 987 9876 98765 89 32 51075176167176176176 347746739 5610
Case #1: 0 Case #2: 25 Case #3: 226 Case #4: 1628 Case #5: 49516 Case #6: 15 Case #7: 15 Case #8: 15 Case #9: 43764 Case #10: 49750 Case #11: 10 Case #12: 51 Case #13: -1 Case #14: 1233 Case #15: 22374
题目要求斐波那契数列前100000项的所有数,之后输入一个数对比看其是否为斐波那契数列的某一项的前缀,如果是那就输出对应的第几项,如果不是那就输出-1.(输入最多40个字符)
首先求斐波那契我们应该都会吧!由于输入最多40个字符也就是说最多查询斐波那契数列前40位数,所以我们计算斐波那契数列前40位就ok!不过怎么计算呢?
如果位数超过40位就将位数降1?然后依次循环?
仔细想想!我举个例子:
假若保留3位数字!435+699=1134,699+1134=1833,1134+1833=2976,1833+2976=4800,2976+4800=7767!假若我们超过了第3位,那么从第一个式子开始,我们退一位!结果会是怎样?:69+113=182(才第一步就错了) 113+182=295(继续错)182+295=477(更加错!);也许有人会说是第一步没进位造成的,那么我们进一个位:69+113+1=183(前三位对了!) 113+183=296(又对了!有希望!)183+296=479(唉,最终还是wa!!哪怕进位了还是只到了第三步就错!!!)
如果我们进位不这样写难道还有更好的办法吗???
当然不是!刚才虽然确实是有错误,可是这只是对于第2位造成的误差,等位数多了也一定会造成误差,只不过!!误差只是该位的前几位!当然算的越多可能误差的位数越多,但是误差的位数增长速度并不大!所以我们要算前40位,那么可以到55位再开始保留位数,一定确保前40位肯定没有一丁点误差!!(就是因为这个原因刚开始总是保留40,41,42,43,,45位数,都试过了,但就是w!a!,当我看了题解才发现其实方法完全一样!只是保留的位数不同,这样就导致的精度有了很大区别,因此!!我们发现大数其实也是有精度的。。。还有一点感悟就是精度啥的一定越精越好吧!就好比数组开的越大越好吧,前提是不mle,哈哈)
解决完斐波那契的精度,再来看查询!
由于有查询,而且斐波那契数列的位数很多,我们要想办法去存呀!比对前缀不是trie树吗?,所以把斐波那契数列都存到trie树里面不就得了!
至于trie树没啥好说的了,时间长了会觉得trie树越来越简单的!
ac代码:
#include <iostream> #include <stdio.h> #include<string.h> #include<algorithm> using namespace std; struct TrieNode{ int id; TrieNode *next[10]; TrieNode(){ id=-1; memset(next,0,sizeof next); } }root; void InsertNode(char *s,int id){ int k=0; TrieNode *p=&root; while(s[k]!='\0') { if(!p->next[s[k]-'0'])p->next[s[k]-'0']=new TrieNode; p=p->next[s[k++]-'0']; if(p->id == -1)p->id=id; } } int SearchTrie(char *s){ int k=0; TrieNode *p=&root; while(s[k]!='\0' && p->next[s[k]-'0'])p=p->next[s[k++]-'0']; if(s[k]!='\0')return -1; return p->id; } char a[65],b[65],c[65]; void init() { memset(a,'0',sizeof(a)); memset(b,'0',sizeof(b)); memset(c,'0',sizeof(c)); int t=0,num=2; a[0]='1',a[1]='\0';b[0]='1',b[1]='\0'; InsertNode(a,t++); InsertNode(b,t++); a[1]='0';b[1]='0'; while(num<100000) { for(int i=0;i<64;i++) { if(a[i]+b[i]+c[i]-'0'-'0'-'0'>9) c[i+1]+=1,c[i]+=a[i]+b[i]-10-'0'-'0'; else c[i]+=a[i]+b[i]-'0'-'0'; }//cout<<"c "<<c<<endl; int bj; for(int i=64;i>=0;i--) if(c[i]!='0') { bj=i;break; } if(bj>55) { for(int i=0;i<63;i++) b[i]=b[i+1],c[i]=c[i+1]; bj--; } char jl[65]; int i; for(i=0;i<65;i++) { jl[i]=c[bj--]; if(i==39)break; if(bj==-1)break; } jl[i+1]='\0'; //cout<<jl<<endl; InsertNode(jl,t++); strcpy(a,b);//cout<<"a "<<a<<endl; strcpy(b,c);//cout<<"b "<<b<<endl; memset(c,'0',sizeof(c)); num++; } } int main() { init(); char x[60];int o=1,t; cin>>t; while(t--) { cin>>x; printf("Case #%d: %d\n",o++,SearchTrie(x)); } return 0; }