1. 程式人生 > >UVA-12333 Revenge of Fibonacci

UVA-12333 Revenge of Fibonacci

不難 .org 序號 item code ret php 壓入 理解

題目鏈接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3755

題目大意:

意思不難理解,就是找到以某個字符串為前綴的最小的斐波拉契數列,並輸出是第幾個斐波拉契數。找不到就輸出-1;

思路:大數加法,字典樹。

ps:通過這道題接觸到了大數加法。(雖然之前在劉汝佳的那本算法書裏看到過階乘的,但當時匆匆略過了)

該題是多組輸入,我們就對斐波拉契數列預處理,將1——100000的斐波拉契數列找出來。

將它們存入字典樹。長度超過40的就只壓入長度為41的前綴。

然後在每個節點存入以當前前綴為最小的斐波拉契數的序號。

ps:斐波拉契數列不能多存了一個!只要你超過了100000個就wa,它卡了這個點;

之所以不全部存入是為了節省空間。不然會RE。

然後代碼應該就能AC了。

ps:本人代碼跑了8330ms,感覺都要tle了。看到他們都是幾百ms就ac了,不造怎麽寫的。時間問題就沒有去看。

代碼如下

 1 #include<iostream>
 2 #include<stdio.h>
 3 using namespace std;
 4 string fib(string s1,string s2)
 5 {
 6     if(s1.length()<s2.length())
7 { 8 string temp=s1; 9 s1=s2; 10 s2=temp; 11 } 12 int i,j; 13 for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--) 14 { 15 s1[i]=char(s1[i]+(j>=0?s2[j]-0:0)); 16 if(s1[i]-0>=10) 17 { 18 s1[i]=char((s1[i]-0)%10+0);
19 if(i) s1[i-1]++; 20 else s1=1+s1; 21 } 22 } 23 return s1; 24 } 25 string a[100002]; 26 int cnt=1; 27 int sum[10000050][11]; 28 int num[10000050]; 29 void add(string s,int number) 30 { 31 int root=0; 32 for(int i=0;i<s.length()&&i<42;i++) 33 { 34 int xx=s[i]-0; 35 if(!sum[root][xx]) 36 { 37 sum[root][xx]=cnt++; 38 num[sum[root][xx]]=number;//存入最小的前綴,因為數列本身就是從小到大排,存入序號就ok 39 } 40 root=sum[root][xx]; 41 } 42 } 43 int Find(string s) 44 { 45 int root=0; 46 for(int i=0;i<s.length();i++) 47 { 48 int xx=s[i]-0; 49 root=sum[root][xx]; 50 if(root==0) 51 return 0; 52 } 53 return num[root]; 54 } 55 int main() 56 { 57 a[1]="1"; 58 a[2]="1"; 59 add(a[1],1); 60 add(a[2],2); 61 for(int i=3;i<=100000;i++)//預處理 62 { 63 a[i]=fib(a[i-1],a[i-2]); 64 add(a[i],i); 65 } 66 int T; 67 while(cin>>T) 68 { 69 int t=0; 70 string st; 71 while(T--) 72 { 73 t++; 74 cin>>st; 75 int tmp=Find(st); 76 if(tmp){ 77 cout<<"Case #"<<t<<": "<<tmp-1<<endl;//因為題目從0開始算,所以減一 78 }else{ 79 cout<<"Case #"<<t<<": "<<-1<<endl; 80 } 81 } 82 } 83 return 0; 84 }

UVA-12333 Revenge of Fibonacci