题意

给定一个形如 图片说明 的式子,求第n项。

方法一(暴力求解):

暴力递推得到第n项

class Solution {
public:
    /**
     * 输出序列的第n项
     * @param n long长整型 序列的项数
     * @param b long长整型 系数
     * @param c long长整型 系数
     * @return long长整型
     */
    long long nthElement(long long n, long long b, long long c) {
        long long last1 = 0,last2 = 1,now;
        const long long mod = 1e9 + 7;
        for (long long i = 0;i < n;++ i) {
            now = (last1 * b) % mod + (last2 * c) % mod;
            now %= mod;
            last2 = last1;
            last1 = now;
        }
        return now;
    }
};

时间复杂度因为是一个一个推过去,所以为图片说明
空间复杂度与n无关,为图片说明

方法二(正解)

首先我们有快速幂,利用二分,在图片说明 的时间内完成求幂。原理是乘法结合律。
而矩阵也同样满足乘法结合律,所以也有类似的方法,称为矩阵快速幂。

看到这种形如图片说明 式子,我们都可以利用矩阵乘法,构造出一个矩阵。因为对于矩阵,我们有矩阵快速幂,可以在图片说明 的时间内快速得出答案。
我们可以构造矩阵图片说明 ,通过公式图片说明 进行递推
每次递推一项,只需要乘上一个图片说明即可。
对于第n项,只需要计算图片说明 的n-1次方即可。

const long long mod = 1e9+7;
class mat{    //矩阵类 
public:
    long long a[2][2];
    mat() {
        memset(a,0,sizeof a);
    }
};
mat mul(const mat& a,const mat& b) {    //2*2矩阵相乘 
    mat res;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            for (int u = 0; u < 2; u++) { 
                res.a[i][j] += (a.a[i][u]*b.a[u][j])%mod;
                res.a[i][j] %= mod;
            }
        }
    }
    return res;
}
mat pow(mat x,long long k) {    //矩阵快速幂 
    if (k == 1) {
        return x;
    }
    long long l = k >> 1;
    mat half = pow(x,l);
    half = mul(half,half);
    if (k & 1) {
        half = mul(x,half);
    }
    return half;
}
class Solution {
public:
    /**
     * 输出序列的第n项
     * @param n long长整型 序列的项数
     * @param b long长整型 系数
     * @param c long长整型 系数
     * @return long长整型
     */
    long long nthElement(long long n, long long b, long long c) {
        mat x;    //构造矩阵 
        x.a[0][0] = b;x.a[0][1] = 1;
        x.a[1][0] = c;x.a[1][1] = 0;
        x = pow(x,n-1);
        return x.a[0][0];
    }
};

很显然,使用矩阵快速幂后,时间复杂度为图片说明 空间复杂度也为图片说明 (因为这里采用了递归的方式,深度为图片说明 ,所以空间复杂度也是与其成正比。如果采用迭代的方式,可以降至图片说明 )