標籤:des style http color java 使用 os strong
Fibonacci Numbers
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1766 Accepted Submission(s): 695
Problem DescriptionThe Fibonacci sequence is the sequence of numbers such that every element is equal to the sum of the two previous elements, except for the first two elements f0 and f1 which are respectively zero and one.
What is the numerical value of the nth Fibonacci number?
InputFor each test case, a line will contain an integer i between 0 and 108 inclusively, for which you must compute the ith Fibonacci number fi. Fibonacci numbers get large pretty quickly, so whenever the answer has more than 8 digits, output only the first and last 4 digits of the answer, separating the two parts with an ellipsis (“...”).
There is no special way to denote the end of the of the input, simply stop when the standard input terminates (after the EOF).
Sample Input
0123453536373839406465
Sample Output
0112359227465149303522415781739088169632459861023...41551061...77231716...7565
題解及代碼:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#define s_5 sqrt(5.0)#define sl_5 (0.5+sqrt(5.0)/2.0)#define sr_5 (0.5-sqrt(5.0)/2.0)using namespace std;int fibo[50];void init(){ fibo[0]=0; fibo[1]=1; int i; for(i=2;i<=50;i++) { fibo[i]=fibo[i-1]+fibo[i-2]; if(fibo[i]>=100000000) { break; } }}struct mat{ long long t[2][2]; void set() { memset(t,0,sizeof(t)); }}a,b;mat multiple(mat a,mat b,int n,int p){ int i,j,k; mat temp; temp.set(); for(i=0;i<n;i++) for(j=0;j<n;j++) { if(a.t[i][j]) for(k=0;k<n;k++) temp.t[i][k]=(temp.t[i][k]+a.t[i][j]*b.t[j][k])%p; } return temp;}mat quick_mod(mat b,int n,int p){ mat t; t.t[0][0]=1; t.t[0][1]=0; t.t[1][0]=0; t.t[1][1]=1; while(n) { if(n&1) { t=multiple(t,b,2,p); } n>>=1; b=multiple(b,b,2,p); } return t;}void init1(){ b.t[0][0]=1; b.t[0][1]=1; b.t[1][0]=1; b.t[1][1]=0;}int main(){ int n; init(); while(cin>>n) { if(n<40) { cout<<fibo[n]<<endl; continue; } double s=log10(1.0/s_5)+n*log10(sl_5); int len=(int)s+1; double t=s-len+4; cout<<(int)pow(10.0,t); init1(); a=quick_mod(b,n,10000); printf("...%04d\n",a.t[1][0]); } return 0;}/*一道比較簡單的數學題,輸出斐波那契數的前四位和後四位。對於前40項,直接打表輸出就可以了。接下來我們講一下大於40位的時候如何計算:對於後四位,我們可以想到,我們進行滾動數組取餘就能求得答案,但是資料量有點大,這樣可定會逾時,所以只能使用矩陣快速冪來加速。對於前四位,我們要使用到斐波那契數的封閉公式:f[n]=1/sqrt(5)*{[0.5+sqrt(5)/2]^n-[0.5-sqrt(5)/2]^n};由於n很大時,[0.5-sqrt(5)/2]^n很小,幾乎可以忽略,又因為我們計算的是前四位,所以不必管後面的精度,所以這一項可以省略。f[n]=1/sqrt(5)*[0.5+sqrt(5)/2]^n;我們假定t=f[n],k為其前四位,想要求t的前四位元k,我們可以使用科學計數法來寫一下t,t=k.xxxx……*10^(len-4);這裡len指的是t的位元。而計算一個數的位元可以使用log10(t)+1來計算得到。那麼知道了這些就很好計算了:首先我們先求出t的位元len=log10(1/sqrt(5)*[0.5+sqrt(5)/2]^n);化簡一下:len=log10(1/sqrt(5))+n*log10(0.5+sqrt(5)/2);對於t=k.xxxx……*10^(len-4);我們兩邊進行log10取對數,得到log10(t)=log10(k.xxxx……)+len-4;化簡一下得到log10(k.xxxx……)=log10(t)-(len-4);那麼我們為了得到k.xxx……,我們可以求10^[log10(t)-(len-4)]就行了,最後一項,對k取整。*轉載請註明出處,謝謝。*/