矩阵快速幂。

题意:
一组数的递推公式如下:F(1)=a,F(2)=b,F(n)=F(n-1)+2* F(n-2)+图片说明 (n>2)。现要求出该序列中的第n个数。

思路:
由于n的值太大,直接递推不行,这里采用构造系数矩阵的方法。
本人目前的理解:当以递归得到数的效率太低时,可以研究递归过程,拆分或者合并公式中的数,研究两个过程的数之间的关系并建立一个矩阵,建立系数矩阵以系数矩阵的幂代替递归。诸如此类的还有求第n个斐波那契数。
观察发现递推过程中的数有:F(n),F(n-1),图片说明,而下一个递推过程中的数有:F(n+1),F(n),图片说明 ,我们要想办法通过第一个过程得到第二个过程。发现第二个过程需要图片说明 ,因此要再加入图片说明,图片说明,n,1构造矩阵[F(n),F(n-1),图片说明,图片说明,图片说明,n,1]的系数矩阵。

代码:

#include <iostream>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cctype>
#include <functional>
#include <string>
#include <cstring>
#include <sstream>
#include <deque>
#define fir first
#define sec second
using namespace std;

typedef long long ll;
typedef pair<int,int> P;
typedef pair<P,int> Q;

const int inf1=2e9+9;
const ll inf2=8e18+9;
const ll mol=2147493647;//1e9+7;
const int maxn=1e5+9;
const ll maxx=1e12+9;

const int sz=7;
struct mat
{
    ll a[sz][sz];
};
ll t,a,b;

mat mul_mat(mat a,mat b)
{
    mat res;
    for(int i=0;i<sz;i++)
        for(int j=0;j<sz;j++)
        {
            res.a[i][j]=0;
            for(int k=0;k<sz;k++)
                res.a[i][j]=(res.a[i][j]+a.a[i][k]*b.a[k][j])%mol;
        }
    return res;
}
mat mat_q_pow(mat x,ll t)
{
    mat res;
    for(int i=0;i<sz;i++)
        for(int j=0;j<sz;j++)
            if(i==j) res.a[i][j]=1;
            else res.a[i][j]=0;
    while(t)
    {
        if(t&1) res=mul_mat(x,res);
        x=mul_mat(x,x);
        t>>=1;
    }
    return res;
}
ll cal(mat ar)
{
    return (ar.a[1][0]*b+ar.a[1][1]*a+ar.a[1][2]*16+ar.a[1][3]*8+ar.a[1][4]*4+ar.a[1][5]*2+ar.a[1][6])%mol;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld%lld",&t,&a,&b);
        mat ar={
            1,2,1,4,6,4,1,
            1,0,0,0,0,0,0,
            0,0,1,4,6,4,1,
            0,0,0,1,3,3,1,
            0,0,0,0,1,2,1,
            0,0,0,0,0,1,1,
            0,0,0,0,0,0,1
                };
        ar=mat_q_pow(ar,t-1);
        if(t==1) printf("%lld\n",a);
        else if(t==2) printf("%lld\n",b);
        else printf("%lld\n",cal(ar));
    }
}