Recursive sequence HDU - 5950 (递推 矩阵快速幂优化)

Posted mrzdtz220

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Recursive sequence HDU - 5950 (递推 矩阵快速幂优化)相关的知识,希望对你有一定的参考价值。

 

题目链接

F[1] = a, F[2] = b, F[i] = 2 * F[i-2] + F[i-1] + i ^ 4, (i >= 3)

现在要求F[N]

类似于斐波那契数列的递推式子吧, 但是N最大能到int的最大值, 直接循环推解不了

所以就得用矩阵快速幂咯

现在就看转移矩阵长什么样了

Mi表示要求的矩阵 转移矩阵用A表示

A * Mi = Mi+1

矩阵Mi里面至少得有 F[i-1] F[i-2] i ^ 4 Mi+1就相应的有 F[i] F[i-1] (i+1)^4

(i+1)^4 = i^4 + 4 * i ^ 3 + 6 * i ^ 2 + 4 * i + 1

所以Mi中还得有i^3 i^2 i 1

总共就有七个元素

$egin{pmatrix} 1 & 2 & 1 & 0 & 0 & 0 & 0 \ 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 & 1end{pmatrix}
imes egin{pmatrix} f_{i-1} \ f_{i-2} \ i^{4} \ i^{3} \ i^{2} \ i \ 1 end{pmatrix} = egin{pmatrix} f_{i} \ f_{i-1} \ (i+1)^{4} \ (i+1)^{3} \ (i+1)^{2} \ i+1 \ 1 end{pmatrix}$

基本的矩阵运算,就是前面这个相当于系数的矩阵得是 (n-2)次幂 因为f1 f2都求过了

初始的矩阵是 

$egin{pmatrix} f_{2} \ f_{1} \ 3^{4} \ 3^{3} \ 3^{2} \ 3 \ 1 end{pmatrix}$

也就是

$egin{pmatrix} b \ a \ 81 \ 27 \ 9 \ 3 \ 1 end{pmatrix}$

特判一下n == 1 和 2的情况就好啦

代码如下

技术图片
#include <cstdio>
#define ll long long
#define MOD 2147493647
using namespace std;

struct Matrix {
    ll m[7][7];
    Matrix() {
        for (int i = 0; i < 7; i++) 
            for (int j = 0; j < 7; j++) 
                m[i][j] = 0;
    }
};

Matrix mul(Matrix A, Matrix B) {
    Matrix temp;
    for (int i = 0; i < 7; i++)
        for (int j = 0; j < 7; j++) 
            for (int k = 0; k < 7; k++) 
                temp.m[i][j] = (temp.m[i][j] % MOD+ A.m[i][k] * B.m[k][j] % MOD) % MOD;
    return temp;
}

Matrix quick_mod(Matrix A, ll b) {
    Matrix ans;
    for (int i = 0; i < 7; i++)
        ans.m[i][i] = 1;
    while (b) {
        if (b & 1) ans = mul(ans, A);
        A = mul(A, A);
        b >>= 1;
    }
    return ans;
}

int main() {
    int T; scanf("%d", &T);
    while (T--) {
        int n, a, b;
        scanf("%d%d%d", &n, &a, &b);
        if (n == 1) printf("%d
", a);
        else if (n == 2) printf("%d
", b);
        else {
            Matrix ans;
            ans.m[0][0] = 1, ans.m[0][1] = 2, ans.m[0][2] = 1;
            ans.m[1][0] = 1;
            ans.m[2][2] = 1, ans.m[2][3] = 4, ans.m[2][4] = 6, ans.m[2][5] = 4, ans.m[2][6] = 1;
            ans.m[3][3] = 1, ans.m[3][4] = 3, ans.m[3][5] = 3, ans.m[3][6] = 1;
            ans.m[4][4] = 1, ans.m[4][5] = 2, ans.m[4][6] = 1;
            ans.m[5][5] = 1, ans.m[5][6] = 1, ans.m[6][6] = 1;
            ans = quick_mod(ans, (ll)n - 2);
            Matrix temp;
            temp.m[0][0] = b, temp.m[1][0] = a, temp.m[2][0] = 81, temp.m[3][0] = 27;
            temp.m[4][0] = 9, temp.m[5][0] = 3, temp.m[6][0] = 1;
            ans = mul(ans, temp);
            printf("%lld
", ans.m[0][0] % MOD);
        }
    }
    return 0;
}
View Code

其实可以封装一下Matrix 重载一下 * 和 ^ 运算符 这样就很方便也很好看啦

以上是关于Recursive sequence HDU - 5950 (递推 矩阵快速幂优化)的主要内容,如果未能解决你的问题,请参考以下文章

Recursive sequence HDU - 5950

HDu 5950 Recursive sequence(矩阵快速幂)

HDU5950-Recursive sequence(矩阵快速幂)

HDU 5950 Recursive sequence 矩阵快速幂

Recursive sequence HDU - 5950

HDU 5950 Recursive sequence 递推+矩阵快速幂 (2016ACM/ICPC亚洲区沈阳站)