2014新生暑假个人排位赛05 D. Fibnacci

Fibonacci变种算法
本文介绍了一种基于Fibonacci数列的变种算法,该算法定义了一个新的数列f(n),并提供了高效的计算方法来求解大数值n下的f(n)值,通过矩阵快速幂的方式优化递归计算过程。
时间限制 1000 ms 内存限制 65536 KB

题目描述

已知函数f,f(0)=f(1)=1,对于所有n>=2,f(n)=f(n-1)+f(n-2)+n。给定n,求f(n)。

输入格式

第一行一个整数t,表示组数,t<1000。之后t行每行一个整数n,0<=n<=1e9。

输出格式

对于每组测试组,输出一行f(n)%1000000007.

输入样例

6
1
2
3
4
5
1000000000

输出样例

1
4
8
16
29
999999980
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <fstream>
#define mod 1000000007
using namespace std;

class Matrix
{
public:
    int matr[2][2];
    Matrix(const Matrix&rhs);
    Matrix(int a, int  b, int  c, int d );
    Matrix& operator=(const Matrix&);
    friend Matrix operator*( Matrix lhs, Matrix rhs)
    {
        Matrix ret(0,0,0,0);
        int i,j,k;
        for(i=0; i<2; i++)
            for(j=0; j<2; j++)
                for(k=0; k<2; k++)
                    ret.matr[i][j]=((long long)lhs.matr[i][k]*rhs.matr[k][j]+ret.matr[i][j])%mod;
        return ret;
    }
};

Matrix::Matrix(int a, int  b, int  c, int  d)
{
    this->matr[0][0] = a;
    this->matr[0][1] = b;
    this->matr[1][0] = c;
    this->matr[1][1] = d;
}

Matrix::Matrix(const Matrix &rhs)
{
    this->matr[0][0] = rhs.matr[0][0];
    this->matr[0][1] = rhs.matr[0][1];
    this->matr[1][0] = rhs.matr[1][0];
    this->matr[1][1] = rhs.matr[1][1];
}

Matrix& Matrix::operator =(const Matrix& rhs)
{
    this->matr[0][0] = rhs.matr[0][0];
    this->matr[0][1] = rhs.matr[0][1];
    this->matr[1][0] = rhs.matr[1][0];
    this->matr[1][1] = rhs.matr[1][1];
    return *this;
}


Matrix power(Matrix m,int b)
{
    Matrix ans(1,0,0,1);
    while(b)
        if(b&1)  b--,ans=ans*m;
        else  b>>=1,m = m*m;
    return ans;
}


int fib (int n)
{
    Matrix matrix0(1, 1, 1, 0);
    Matrix ec(0,0,0,0);
    matrix0 = power(matrix0, n-1);
    ec.matr[0][0] = ((long long)matrix0.matr[0][0]*5+ (long long)matrix0.matr[0][1]*4)%mod;
    return ((ec.matr[0][0]-n-3)%mod+mod)%mod;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        printf("%d\n",fib(n));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值