扩展Fibonacci数

问题描述:

定义一组叫做扩充的Fibonacci数如下,己知X与Y 两个数,于是扩充Fibonacci数 Fi 为:
Fi=11XFi2+YFi1i=1i=2i>2
因此,当X=Y=l 时,这一组扩充的Fibonacci 数就变成一般的Fibonacci 数了,现在请写一个函数,
接收一个n 值,不用数组与递归的方法算出下面的结果:
F0Fn+F1Fn1++FiFni++Fn1F1+FnF0

#include<iostream>
using namespace std;

/* 定义一组叫做扩充的Fibonacci数如下,己知X与Y 两个数,于是扩充Fibonacci数Fi为: | 1, i=1 Fi=| 1, i=2 | X*Fi-2+ Y*Fi-1 因此,当X=Y=l 时,这一组扩充的Fibonacci 数就变成一般的Fibonacci 数了, 现在请写一个函数,接收一个n 值,不用数组与递归的方法算出下面的结果: F0*Fn + F1*Fn-1 +…+ Fi*Fn-i +…+ Fn-1*F1 +FnF0 */


class U4X4Matrix
{
public:
    unsigned long A[4][4];

public:
    //赋值构造函数
    U4X4Matrix(unsigned long B[4][4]){

        for (int i(0); i < 4; i++)
        for (int j(0); j < 4; j++)
            A[i][j] = B[i][j];
    }
    //赋值复制构造函数
    U4X4Matrix(const U4X4Matrix &m){
        for (int i(0); i < 4; i++)
        for (int j(0); j < 4; j++)
            A[i][j] = m.A[i][j];    
    }
    //拷贝复制构造函数
    U4X4Matrix operator = (const U4X4Matrix &m){
        for (int i(0); i < 4; i++)
        for (int j(0); j < 4; j++)
            A[i][j] = m.A[i][j];
        return *this;
    }

    //A * leftMatrix
    void U4X4MatrixRightMul(U4X4Matrix leftMatrix){
        U4X4Matrix temp = *this;

        for (int i(0); i < 4;i++)
        for (int j(0); j < 4; j++)
        {
            A[i][j] = temp.A[i][0] * leftMatrix.A[0][j] + temp.A[i][1] * leftMatrix.A[1][j] +
                temp.A[i][2] * leftMatrix.A[2][j] + temp.A[i][3] * leftMatrix.A[3][j];
        }
    }

    void U4X4Matrix_Power_N(int n){

        if (n == 1) return;
        if (n % 2 == 0){

            U4X4Matrix_Power_N(n >> 1);
            U4X4Matrix temp = *this;
            U4X4MatrixRightMul(temp);
            return;
        }
        U4X4Matrix temp1 = *this;
        U4X4Matrix_Power_N(n >> 1);
        U4X4Matrix temp2 = *this;
        U4X4MatrixRightMul(temp1);
        U4X4MatrixRightMul(temp2);
    }

};




unsigned long BroadFibonacci_v1(const unsigned long  &n, const unsigned long &x, const unsigned long &y){

    unsigned tempF, tempA;
    unsigned Fnminus1(1), Fnminus2(1);
    unsigned Anminus1(2), Anminus2(1);

    for (int i(2); i <n; i++){

        tempF = Fnminus1;
        Fnminus1= y*Fnminus1 + x*Fnminus2;
        Fnminus2 = tempF;

        tempA = Anminus1;
        Anminus1 = y*Anminus1 + x*Anminus2 + (1-y)*Fnminus2 + Fnminus1;
        Anminus2 = tempA;
    }

    return Anminus1;

}


unsigned long BroadFibonacci_v2(const unsigned long  &n, const unsigned long &x, const unsigned long &y){


    unsigned long MatrixArray[4][4] = {
        { y, x, 1, x },
        { 1, 0, 0, 0 },
        { 0, 0, y, x },
        { 0, 0, 1, 0 }
    };

    U4X4Matrix _4x4Matrix(MatrixArray);

    _4x4Matrix.U4X4Matrix_Power_N(n - 2);

    return _4x4Matrix.A[0][0] * 2 + _4x4Matrix.A[0][1] + _4x4Matrix.A[0][2] + _4x4Matrix.A[0][3];
}

int main(){

    unsigned long x,y; 
    unsigned long n;

    cout << "输入系数x、y和序数n,以空格键分隔" << endl;
    cin >> x >> y>>n;

    cout<<"BroadFibonacci_v1结果:"<<BroadFibonacci_v1(n, x, y)<<endl;
    cout <<"BroadFibonacci_v2结果:" << BroadFibonacci_v2(n, x, y) << endl;

    system("pause");
}

算法说明:

An=F0Fn+F1Fn1++FiFni++Fn1F1+FnF0 于是可以得到 An 的递推关系式:
An=XAn2+YAn1+Fn+XFn1 ,这样就可以用自低向上的方法求出 An ,O(n)=n。
其实这个递推式还可以用矩阵来求解,可以将算法的时间复杂度降低到log(n):

AnAn1FnFn1 = Y100X00010Y1X0X0 An1An2Fn1Fn2

可以化为:

AnAn1FnFn1 = Y100X00010Y1X0X0n2 A2A1F2F1

A2=2,A1=1,F2=1,F1=1

你可能感兴趣的:(fibonacci)