题意:
给定一个长度不超过40的数字串s,求斐波那契数列的前十万项中,最小的一个前缀为s的数的下标。
解决:
高精度算出前十万个斐波那契数,每个取前40位,建trie,查询O(40)
1 #include <bits/stdc++.h> 2 3 int a[22000], b[22000], c[22000]; 4 int l1, l2, l3; 5 int op[55], len; 6 7 struct Node{ 8 Node *ch[10]; 9 int ans; 10 Node() 11 { 12 for (int i = 0; i < 10; ++i) 13 ch[i] = NULL; 14 ans = -1; 15 } 16 }; 17 18 struct Trie{ 19 Node *root; 20 void init() 21 { 22 root = new Node(); 23 } 24 void trieInsert(int index) 25 { 26 Node *p = root; 27 for (int i = l3; i >= std::max(l3-39, 1); --i) { 28 if ( p -> ch[c[i]] == NULL) { 29 p -> ch[c[i]] = new Node(); 30 p-> ch[c[i]] -> ans = index; 31 } 32 p = p ->ch[c[i]]; 33 } 34 p -> ans = index; 35 } 36 int trieQuery() 37 { 38 Node *p = root; 39 for (int i = 1; i <= len; ++i) { 40 if ( p -> ch[op[i]] == NULL) 41 return -1; 42 p = p -> ch[op[i]]; 43 } 44 return p -> ans; 45 } 46 }tr; 47 48 void add() 49 { 50 int carry = 0; 51 for (int i = 1; i <= std::max(l1, l2); ++i) { 52 c[i] = a[i] + b[i] + carry; 53 if (c[i] >= 10) { 54 carry = 1; 55 c[i] -= 10; 56 } 57 else 58 carry = 0; 59 } 60 if (carry == 1) { 61 c[++l3] = 1; 62 } 63 } 64 65 void init() 66 { 67 tr.init(); 68 memset(a, 0, sizeof a); 69 memset(b, 0, sizeof b); 70 memset(c, 0, sizeof c); 71 a[++l1] = 1; 72 b[++l2] = 1; 73 c[++l3] = 1; 74 tr.trieInsert(0); 75 for (int i = 2; i < 100000; ++i) { 76 add(); 77 tr.trieInsert(i); 78 for (int j = 1; j <= l2; ++j) { 79 a[j] = b[j]; 80 } 81 for (int j = 1; j <= l3; ++j) { 82 b[j] = c[j]; 83 } 84 l1 = l2; 85 l2 = l3; 86 } 87 } 88 89 char buf[55]; 90 91 int main() 92 { 93 init(); 94 int T; 95 scanf("%d", &T); 96 for (int t = 1; t <= T; ++t) { 97 scanf("%s", buf+1); 98 len = strlen(buf+1); 99 for (int i = 1; i <= len; ++i) { 100 op[i] = buf[i] - ‘0‘; 101 } 102 printf("Case #%d: %d\n", t, tr.trieQuery()); 103 } 104 }
时间: 2024-10-29 19:08:47