1. 程式人生 > >UVA-12333 Revenge of Fibonacci(豎式加法模擬 & 字典樹)

UVA-12333 Revenge of Fibonacci(豎式加法模擬 & 字典樹)

當前位置 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)
using
namespace 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(豎式加法模擬 & 字典樹)