题意:Fibonacci数的定义为: F(0)=F(1)=1,然后从F(2)开始,F(i)=F(i-1)+F(i-2)。例如,前10项Fibonacci 数分别为1,1,2,3,5,8,13,21,34,55...
有一天晚上,你梦到了Fibonacci,它告诉你一个有趣的Fibonacci 数。醒来以后,你只记得了它的开头几个数字。你的任务是找出以它开头的最小Fibonacci 数的序号。例如以12开头的最小Fibonacci 数是F(25)。
输入不超过40个数字,输出满足条件的序号。如果序号小于100000的Fibonacci 数均不满足条件,输出-1。
提示:本题有一定效率要求。如果高精度代码比较慢,可能会超时。
思路:高精度计算前100000个Fibonacci数,并将每个数字的前50个数存入字典树,然后查询就OK了。
我用原来自己写的大数模板一直超时,不知道为啥我的大数板子那么慢。。。只好手写个加法了
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e5; //Trie树 struct Trie { int id; Trie *Next[10]; Trie() { id = -1; for (int i = 0; i < 10; i++) Next[i] = NULL; } }; void Insert(Trie* root, string s, int id) { Trie* temp = root; for (int i = 0; i < s.size(); i++) { int index = s[i] - '0'; if (temp->Next[index] == NULL) { temp->Next[index] = new Trie; temp->Next[index]->id = id; } temp = temp->Next[index]; } } int Query(Trie* root, string s) { Trie *temp = root; for (int i = 0; i < s.size(); i++) { int index = s[i] - '0'; if (temp->Next[index] == NULL) return -1; temp = temp->Next[index]; } return temp->id; } string add(string a, string b) { int i = a.size()-1, j = b.size()-1, g = 0; string ans; while (i >= 0 || j >= 0 || g) { int x = g; if (i >= 0) x += (a[i] - '0'); if (j >= 0) x += (b[j] - '0'); g = x / 10; ans += (x%10 + '0'); i--; j--; } reverse(ans.begin(), ans.end()); return ans; } int main() { Trie* root = new Trie; string a = "1", b = "1"; Insert(root, "1", 0); Insert(root, "1", 1); for (int i = 2; i < MAXN; i++) { string sum = add(a, b); a = b; b = sum; if (sum.size() > 50) sum = sum.substr(0, 50); Insert(root, sum, i); } int T, CASE = 1; scanf("%d", &T); while (T--) { string str; cin >> str; int ans = Query(root, str); printf("Case #%d: %d\n", CASE++, ans); } return 0; } /* 15 1 12 123 1234 12345 9 98 987 9876 98765 89 32 51075176167176176176 347746739 5610 */