数列-矩阵快速幂

数列

TimeLimit:1000MS  MemoryLimit:64MB
64-bit integer IO format: %lld
已解决 |  点击收藏
Problem Description

已知一个数列的通向公式:F[n] = 2F[n - 1] + 4F[n - 2] + 2F[n - 3],F[1]、F[2]、F[3]均为1。输入n(1 <= n <= 10^18),求F[n]的值。因为数太大,输出对1000000007取模的值。

Input

第一行输入T,表示T组数据,接下来T行,每行一个n,1 <= n <= 10^18。

Output
输出T行,每行输出F[n] % 1000000007的值。
SampleInput
 
    
3
3
6
100
SampleOutput
 
    
1
78
360461226


这题是福建农林大学的校赛,当时并没有做出来,因为那是只学了快速幂,不会构造矩阵TT。

这题n的范围有10^18直接暴力O(n)稳稳超时

先构造矩阵,再用快速幂就可以将时间复杂度降为log2(n)

那么如何构造矩阵呢?

f(n) = a(1)*f(n-1) + a(2)*f(n-2) +...+a(d)*f(n-d)
0 1 0 0 . . . 0
0 0 1 0 . . . 0
0 0 0 1 . . . 0
. . . . . . . 0
. . . . . . . 1

a(d) a(d-1) a(d-2) .... a[1]

构造好矩阵后就可以使用快速幂

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 1000000007
using namespace std;
const int maxn = 3;
struct matrix                                 ///开一个结构体存矩阵
{
    long long M[maxn][maxn];
};

matrix mul(matrix a,matrix b)                           ///矩阵相乘
{
    matrix c;
    for(int i=0; i<maxn; i++)
        for(int j=0; j<maxn; j++)
        {
            c.M[i][j] = 0;
            for(int k=0; k<maxn; k++)
                c.M[i][j] =(c.M[i][j]+ a.M[i][k]*b.M[k][j]%mod)%mod;
        }
    return c;
}

long long Matrix_fast_power(matrix a,matrix b,long long m) ///快速幂
{
    if(m <= 3) return 1;
    m -= 3;
    while(m)
    {
        if(m&1)
            a=mul(a,b);
        m>>=1;
        b=mul(b,b);
    }
    return (a.M[2][0] + a.M[2][1] + a.M[2][2]) % mod;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        long long n;
        scanf("%lld",&n);
        matrix a,b;
        memset(a.M,0,sizeof(a.M));
        memset(b.M,0,sizeof(b.M));
        a.M[0][0]=a.M[1][1]=a.M[2][2]=1;                   ///单位矩阵
        b.M[0][1] = 1,b.M[1][2] = 1,b.M[2][0] = 2,b.M[2][1] = 4,b.M[2][2] = 2;
                                                           ///构造的矩阵
        printf("%lld\n",Matrix_fast_power(a,b,n));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37804064/article/details/79647562