2018年湘潭大学程序设计竞赛 G 又见斐波那契 【矩阵快速幂】


又见斐波那契

Time Limit: 2000/1000 MS(Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Problem Description

这是一个加强版的斐波那契数列。 

给定递推式



F(n)的值,由于这个值可能太大,请对109+7取模。

 

Input

第一行是一个整数T(1 ≤ T ≤ 1000),表示样例的个数。 

以后每个样例一行,是一个整数n(1 ≤ n ≤ 1018)

 

Output

每个样例输出一行,一个整数,表示F(n) mod 1000000007 

 

Sample Input

4

1

2

3

100 

 

Sample Output

1

16

57

558616258


【题目链接】 link


【思路】

由于n很大,还是自然地想到矩阵快速幂,但关键是矩阵的构造问题。

根据题目的表达式,我们主要要寻找的就是几个常数之间的关系。

推算得到:

(i+1)3=i3+3i2+3i+1

(i+1)2=i2+2i+1

i+1=i+1

那么就可以构造矩阵了

有了矩阵后直接套模板即可

#include <cstdio>
#include <bits/stdc++.h>
#include <cmath>
#include <map>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)


typedef long long ll;
const int maxn = 6;
const ll mod = 1e9+7;
const int INF = 1e9;
const double eps = 1e-6;

struct Matrix
{
    ll temp[maxn][maxn];
} a;

void init()
{
    for(int i=0;i<6;i++)
    for(int j=0;j<6;j++)
    {
        a.temp[i][j]=0;
    }
    for(int i=0;i<6;i++) a.temp[0][i]=1;
    a.temp[1][0]=1;
    a.temp[2][2]=a.temp[2][5]=1;
    a.temp[2][3]=a.temp[2][4]=3;
    a.temp[3][3]=a.temp[3][5]=1;
    a.temp[3][4]=2;
    a.temp[4][4]=a.temp[4][5]=1;
    a.temp[5][5]=1;
}

Matrix mul(Matrix a,Matrix b)
{
    Matrix ans;
    for (int i=0; i<maxn; i++)
        for (int j=0; j<maxn; j++)
        {
            ans.temp[i][j]=0;
            for (int k=0; k<maxn; k++)
            {
                ans.temp[i][j]+=(a.temp[i][k]*b.temp[k][j]+mod)%mod;  //特别注意
                ans.temp[i][j]%=mod;
            }
        }
    return ans;
}

void fun(Matrix ans,ll k)
{
    for(int i=0; i<maxn; i++)
        for(int j=0; j<maxn; j++)
            a.temp[i][j]=(i==j);
    while(k)
    {
        if(k%2)
            a=mul(a,ans);
        ans=mul(ans,ans);
        k/=2;
    }
}

int main()
{
    Matrix t;
    ll n;
    for(int i=0;i<maxn;i++)
    for(int j=0;j<maxn;j++)
    {
        t.temp[i][j]=0;
    }
    t.temp[0][0]=1;
    t.temp[2][0]=8;
    t.temp[3][0]=4;
    t.temp[4][0]=2;
    t.temp[5][0]=1;
    rush()
    {
        scanf("%lld",&n);
        init();
        if(n<=1)
        {
            printf("%lld\n",n);
            continue;
        }
        fun(a,n-1);
        a=mul(a,t);
        printf("%lld\n",a.temp[0][0]);
    }
    return 0;
}






猜你喜欢

转载自blog.csdn.net/my_sunshine26/article/details/80104504
今日推荐