UVA-12333 Revenge of Fibonacci(豎式加法模擬 & 字典樹)
阿新 • • 發佈:2019-01-18
當前位置 typedef 出現 字符 space 理解 ++ open end
題目:
給出一個斐波那契數字的前綴,問第一個有這個前綴的數字在斐波那契數列中是第幾個。
思路:
紫書提示:本題有一定效率要求。如果高精度代碼比較慢,可能會超時。
利用滾動數組和豎式加法來模擬斐波那契相加的過程,在這個過程中每得出一個斐波那契數字就用字典樹存一下。
PS:在滾動數組中存的斐波那契數字是逆序存儲的。
代碼:
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define MAX 1e9; #define FRE() freopen("in.txt","r",stdin) #define FRO() freopen("out.txt","w",stdout) usingnamespace std; typedef long long ll; const int maxn = 4000010; struct Node { int next[10]; int id; Node() { for(int i = 0; i<10; i++) { next[i] = -1; } id = -1; } }; Node trie[maxn]; int tot = 0; //Node root = trie[tot++]; int idx(char ch) {return ch-‘0‘;}void Insert(char* str, int id) {//字典樹插入 // int u = 0; // for(int i = 0; i<strlen(str); i++) { // int v = idx(str[i]);//獲取字符串當前位置的數字 // if(trie[u].next[v]==-1) { //如果這個位置是不存在的 // trie[u].next[v] = tot; // u = tot++; // } else { //如果這個位置是存在的 // u = trie[u].next[v];// } // if(trie[u].id==-1) { // trie[u].id = id; // } // } int u = 0; for(int i = 0; i<strlen(str); i++){ int v = idx(str[i]); if(trie[u].next[v]==-1){//如果這個位置不存在 trie[u].next[v] = tot++; } u = trie[u].next[v];//結點往下走 if(trie[u].id==-1){//保存這個斐波那契數字的id trie[u].id = id; } } } int Query(char* str) { int u = 0; for(int i = 0; i<strlen(str); i++) { int v = idx(str[i]); if(trie[u].next[v]==-1) { //說明這個前綴不會出現 return -1; } u = trie[u].next[v]; } return trie[u].id; } int fib[2][maxn]; int main() { FRE(); int s=0,l=1; char f[55]; Insert("1",1); fib[1][0] = 1; fib[0][0] = 0; for(int i=2; i<100000; i++) { int a=i%2, b=(i+1)%2;//滾動數組,可以手動跑兩組斐波那契數字的相加就可以理解了 for(int k=s; k<l; k++) { fib[a][k] = fib[a][k] + fib[b][k]; if(fib[a][k]>=10) { //這位相加可以進位時 fib[a][k+1]++;//下一位加一 fib[a][k] -= 10;//這一位減掉進位的10 if(k==l-1) { //最後一個進位讓l加一 l++; } } } if(l-s>50) { //數組中是倒著存這個數的,l-1表示個位開始,s表示最高位 s++; } int cnt=0; for(int k=l-1; k>=s&&cnt<40; k--){//根據題目提示,只選取前40位即可 f[cnt++] = fib[a][k]+‘0‘; } // if(i==10) // printf("%s\n",f); Insert(f,i); memset(f,0,sizeof(f)); } //cout<<"GG"<<endl; char str[55]; int n; scanf("%d",&n); for(int i=0; i<n; i++){ scanf("%s",str); printf("Case #%d: ",i+1); int ans = Query(str); printf("%d\n",ans==-1 ? -1:ans-1); } return 0; }
UVA-12333 Revenge of Fibonacci(豎式加法模擬 & 字典樹)