hdu4099 Revenge of Fibonacci
Posted 曹孟德
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu4099 Revenge of Fibonacci相关的知识,希望对你有一定的参考价值。
题意:给定fibonacci数列,输入前缀,求出下标。题目中fibonacci数量达到100000,而题目输入的前缀顶多为40位数字,这说明我们只需要精确计算fibinacci数前40位即可。查询时使用字典树。在计算时,为了保证前40位精确无误。在此我计算了前60位。以保证前面不在进位。
注意点:
1)关于表示进位问题,需要控制计算的数位数在60以内,切记计算时不要错位(相同位要对齐)。
2)坑点:题目给出的数插入字典树最好插入前40位即可,否则MLE.
3)坑点:题目只要求计算下标不超过100000,计算到100000或者以上均会WA,因为输出值不是-1
下面是数组的AC代码:824ms
#define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<string> #include<map> #include<fstream> #include<ctime> #include<queue> #include<vector> #include<numeric> #include<string.h> #include<iomanip> #include<sstream> #include<algorithm> using namespace std; typedef pair<int,int> PII; typedef vector<int> BigInterger; const int maxn = 100000; const int maxsize = 10; const int maxnum =65; struct TrieNode{ TrieNode(int d = -1) :id(d){ memset(next, NULL, sizeof(next)); } int id; TrieNode*next[maxsize]; }; TrieNode*T = new TrieNode; void insert(char*str,const int&index){ int len = strlen(str); TrieNode*p = T; int t = 0; for (int i = len-1; i>=0&&t<40;i--,t++){ int id =str[i]-‘0‘; if (!p->next[id])p->next[id] = new TrieNode(index); p = p->next[id]; } } int search(char*str){ TrieNode*p = T; while (*str != ‘\0‘){ int id = *str++ - ‘0‘; if (!p->next[id])return -1; p = p->next[id]; } return p->id; } void init(){ char f[3][maxnum]; f[1][0] =‘1‘; f[1][1] = ‘\0‘; f[0][0] =‘1‘; f[0][1] = ‘\0‘; insert("1", 0); for (int i = 2; i<maxn; i++){ int g = 0,j=0,cnt = 0, x; int r1 = (i - 1) % 3, r2 = (i - 2) % 3, r = i % 3; int lena = strlen(f[r1]); int lenb = strlen(f[r2]); if (lena >= maxnum - 5){ memcpy(f[r1], f[r1]+1, lena - 1); f[r1][lena - 1] = ‘\0‘; memcpy(f[r2], f[r2]+1, lenb - 1); f[r2][lenb - 1] = ‘\0‘; lena--, lenb--; } while (g || j < lena||j<lenb){ x = g; if (j < lena)x += f[r1][j]-‘0‘; if (j < lenb)x += f[r2][j]-‘0‘; f[r][cnt++] = x % 10+‘0‘; g = x / 10; j++; } f[r][cnt] = ‘\0‘; insert(f[r], i); } } int main(){ init(); int T,kase=1; char str[50]; scanf("%d", &T); while(T--){ scanf("%s", str); printf("Case #%d: %d\n",kase++,search(str)); } return 0; }
采用向量AC的代码624ms(传值要用引用,否则多了不必要的复制):
#define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<string> #include<map> #include<fstream> #include<ctime> #include<queue> #include<vector> #include<numeric> #include<string.h> #include<iomanip> #include<sstream> #include<algorithm> using namespace std; typedef pair<int,int> PII; typedef vector<int> BigInterger; const int maxn = 100000; const int maxsize = 10; const int maxnum =65; struct TrieNode{ TrieNode(int d = -1) :id(d){ memset(next, NULL, sizeof(next)); } int id; TrieNode*next[maxsize]; }; TrieNode*T = new TrieNode; void insert(const BigInterger&v,const int&index){ int len=v.size(); TrieNode*p = T; int t = 0; for (int i = len-1; i>=0&&t<40;i--,t++){ int id =v[i]; if (!p->next[id])p->next[id] = new TrieNode(index); p = p->next[id]; } } int search(char*str){ TrieNode*p = T; while (*str != ‘\0‘){ int id = *str++ - ‘0‘; if (!p->next[id])return -1; p = p->next[id]; } return p->id; } //引用传值,避免赋值,效率更高 void add(BigInterger &a, BigInterger &b, BigInterger&c){ int lena = a.size(), lenb = b.size(); int g=0, x,i=0; c.clear(); if (lena > maxnum - 5 || lenb > maxnum - 5){ a.erase(a.begin()), b.erase(b.begin()); lena--, lenb--; } while (g || i < lena || i < lenb){ x = g; if (i < lena)x += a[i]; if (i < lenb)x += b[i]; c.push_back(x % 10); g = x / 10; i++; } } void init(){ BigInterger a[3]; a[0].push_back(1); a[1].push_back(1); insert(a[1], 0); for (int i = 2; i<maxn; i++){ add(a[(i - 1) % 3], a[(i - 2) % 3], a[i % 3]); insert(a[i % 3], i); } } int main(){ init(); int T,kase=1; char str[50]; scanf("%d", &T); while(T--){ scanf("%s", str); printf("Case #%d: %d\n",kase++,search(str)); } return 0; }
以上是关于hdu4099 Revenge of Fibonacci的主要内容,如果未能解决你的问题,请参考以下文章
[ACM] HDU 5086 Revenge of Segment Tree(全部连续区间的和)
HDU 4898 The Revenge of the Princess’ Knight (后缀数组+二分+贪心+...)