1. 程式人生 > >洛谷 P1939 【模板】矩陣加速(數列)——————矩陣快速冪(水題)

洛谷 P1939 【模板】矩陣加速(數列)——————矩陣快速冪(水題)

P1939 【模板】矩陣加速(數列)

題目描述

a[1]=a[2]=a[3]=1

a[x]=a[x-3]+a[x-1] (x>3)

求a數列的第n項對1000000007(10^9+7)取餘的值。

輸入輸出格式

輸入格式:

第一行一個整數T,表示詢問個數。

以下T行,每行一個正整數n。

輸出格式:

每行輸出一個非負整數表示答案。

輸入輸出樣例

輸入樣例#1: 3 6 8 10

輸出樣例#1:

4 9 19

說明

對於30%的資料 n<=100n<=100

對於60%的資料 n<=2107n<=2*10^7

對於100%的資料 T<

=100n<=2109T<=100,n<=2*10^9

構造矩陣 (10+1100010)×(a3a2a1)=(a4a3a2)\begin{pmatrix}1&0+&1\\1&0&0\\0&1&0\end{pmatrix}\times\begin{pmatrix}a_3\\a_2\\a_1\end{pmatrix} =\begin{pmatrix}a_4\\a_3\\a_2\end{pmatrix}

a1=a4a3a2 所以,我們這樣的話 (101100010)n2×(a3a2a1)=(anan1an2)\begin{pmatrix}1&0&1\\1&0&0\\0&1&0\end{pmatrix}^{ n-2}\times\begin{pmatrix}a_3\\a_2\\a_1\end{pmatrix} =\begin{pmatrix}a_n\\a_{n-1}\\a_{n-2}\end{pmatrix}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAXN = 4;
const int INF  = 0x3f3f3f3f;
const int MOD  = 1e9+7;

struct mat{ll m[MAXN][MAXN]; } ;

ll N;
inline mat mul(mat a,mat b)
{
        mat tmp;
        for(int i=1;i<=N;i++)
                for(int j=1;j<=N;j++)
                {
                        tmp.m[i][j]=0;
                        for(int k=1;k<=N;k++)
                                tmp.m[i][j]=(tmp.m[i][j]+a.m[i][k]*b.m[k][j]+MOD)%MOD;
                }
        return tmp;
}
inline mat pow_mod(mat a,ll n)
{
        mat ans;
        memset(ans.m,0,sizeof(ans.m));
        for(int i=1;i<=N;i++)
                ans.m[i][i]=1;

        while(n)
        {
                if(n&1) ans=mul(ans,a);
                a=mul(a,a);
                n>>=1;
        }
        return ans;
}
int main()
{
        ll n;
        N=3;
        mat a,b;
        memset(a.m,0,sizeof(a.m));
        memset(b.m,0,sizeof(b.m));
        a.m[1][1]=1;
        a.m[2][1]=1;
        a.m[3][1]=1;
        b.m[1][1]=1;b.m[1][3]=1;
        b.m[2][1]=1;
        b.m[3][2]=1;
        int t;
        scanf("%d",&t);
        while(t--)
        {
                scanf("%lld",&n);
                if(n<=3)//之前沒寫這個,TLE了好幾次
                {
                        printf("1\n");
                        continue;
                }
                mat c=pow_mod(b,n-2);
                mat d=mul(c,a);
                printf("%lld\n",d.m[2][1]);
        }
        return 0;
}