HDU 3117 Fibonacci Numbers(Fibonacci矩陣加速遞推+公式)

畫船聽雨發表於2014-09-29

題目意思很簡單:求第n個Fibonacci數,如果超過八位輸出前四位和後四位中間輸出...,否則直接輸出Fibonacci數是多少。

後四位很好求,直接矩陣加速遞推對10000取餘的結果就是。

前四位搜了一下:http://blog.csdn.net/xieqinghuang/article/details/7789908

Fibonacci的通項公式,對,fibonacci數是有通項公式的——

f(n)=1/sqrt(5)(((1+sqrt(5))/2)^n+((1-sqrt(5))/2)^n)

假設F[n]可以表示成 t * 10^k(t是一個小數),那麼對於F[n]取對數log10,答案就為log10 t + K,此時很明顯log10 t<1,於是我們去除整數部分,就得到了log10 t ,
再用pow(10,log10 t)我們就還原回了t。將t×1000就得到了F[n]的前四位。 具體實現的時候Log10 F[n]約等於((1+sqrt(5))/2)^n/sqrt(5),這裡我們把((1-sqrt(5))/2)^n這一項忽略了,
因為當N>=40時,這個數已經小的可以忽略。於是log10 F[n]就可以化簡成log10 1/sqrt(5) + n*log10 (1+sqrt(5))/2

通過求對數可以得到fibonacci數。

還有就是其實後四位存在一個迴圈節沒15000個會重複一次。

Fibonacci Numbers

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1882    Accepted Submission(s): 738


Problem Description
The 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?
 

Input
For 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
0 1 2 3 4 5 35 36 37 38 39 40 64 65
 

Sample Output
0 1 1 2 3 5 9227465 14930352 24157817 39088169 63245986 1023...4155 1061...7723 1716...7565
 

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-10
///#define M 1000100
#define LL __int64
///#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)

///#define mod 9973

int mod;
const int maxn = 2010;

using namespace std;

struct matrix
{
    int f[110][110];
};

matrix mul(matrix a, matrix b, int n)///矩陣乘法
{
    matrix c;
    memset(c.f, 0, sizeof(c.f));
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            for(int k = 0; k < n; k++) c.f[i][j] += a.f[i][k]*b.f[k][j];
            c.f[i][j] %= mod;
        }
    }
    return c;
}

matrix pow_mod(matrix a, int b, int n)///矩陣快速冪
{
    matrix s;
    memset(s.f, 0 , sizeof(s.f));
    for(int i = 0; i < n; i++) s.f[i][i] = 1;
    while(b)
    {
        if(b&1) s = mul(s, a, n);
        a = mul(a, a, n);
        b >>= 1;
    }
    return s;
}

matrix Add(matrix a,matrix b, int n)  ///矩陣加法
{
    matrix c;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            c.f[i][j] = a.f[i][j]+b.f[i][j];
            c.f[i][j] %= mod;
        }
    }
    return c;
}

LL num[maxn];

int main()
{
    num[0] = 0LL;
    num[1] = 1LL;
    for(int i = 2; i <= 40; i++) num[i] = num[i-1]+num[i-2];
    mod = 10000;
    int n;
    while(cin >>n)
    {
        if(n < 40)
        {
            cout<<num[n]<<endl;
            continue;
        }
        double ans;
        ans = -0.5*(log10(5.0))+n*log10((sqrt(5.0)+1.0)/2);
        ans -= (int)ans;
        ans = pow(10, ans);
        while(ans < 1000) ans *= 10;
        printf("%d",(int)ans);
        cout<<"...";
        matrix c;
        memset(c.f, 0, sizeof(c.f));
        c.f[0][0] = 1;
        c.f[0][1] = 1;
        c.f[1][0] = 1;
        matrix d;
        d = pow_mod(c, n-2, 2);
        int sum = 0;
        sum += d.f[0][0] + d.f[0][1];
        sum %= mod;
        if(sum < 10) cout<<"000";
        else if(sum < 100) cout<<"00";
        else if(sum < 1000) cout<<"0";
        cout<<sum<<endl;
    }
    return 0;
}


相關文章