hdu 3117 Fibonacci Numbers

來源:互聯網
上載者:User

標籤:des   style   http   color   java   使用   os   strong   

Fibonacci NumbersTime 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取整。*轉載請註明出處,謝謝。*/





聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.