HDU 5950题解(矩阵快速幂)

HDU 5950
  • 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5950
  • 根据题目大意可得如下的递推公式,其中a和b分别由外部输入,对于给定 n n n,求 f ( n ) f(n) f(n)
    { f ( 1 ) = a ( n = 1 ) f ( 2 ) = b ( n = 2 ) f ( n ) = f ( n − 1 ) + 2 f ( n − 2 ) + n 4 ( n ≥ 3 ) \begin{cases} f(1)=a & (n=1) \\ f(2)=b & (n=2) \\ f(n)=f(n-1)+2f(n-2)+n^{4} & (n\geq3) \end{cases} f(1)=af(2)=bf(n)=f(n1)+2f(n2)+n4(n=1)(n=2)(n3)
  • 通过上面的递推式可以知道 f ( n + 1 ) f(n+1) f(n+1) f ( n ) f(n) f(n) f ( n − 1 ) f(n-1) f(n1) n 4 n^{4} n4 n 3 n^{3} n3 n 2 n^{2} n2 n n n 1 1 1有关
    所以可以得到如下的关系
    { ​ f ( n ) ​ ​ f ( ​ n ​ − ​ 1 ​ ) ​ ​ n ​ 4 ​ ​ n ​ 3 ​ ​ n ​ 2 ​ ​ n ​ ​ 1 ​ } { ​ 1 ​ ​ 1 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ 2 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ 1 ​ ​ 0 ​ ​ 1 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ 4 ​ ​ 0 ​ ​ 4 ​ ​ 1 ​ ​ 0 ​ ​ 0 ​ ​ 0 ​ 6 ​ ​ 0 ​ ​ 6 ​ ​ 3 ​ ​ 1 ​ ​ 0 ​ ​ 0 ​ 4 ​ ​ 0 ​ ​ 4 ​ ​ 3 ​ ​ 2 ​ ​ 1 ​ ​ 0 ​ 1 ​ ​ 0 ​ ​ 1 ​ ​ 1 ​ ​ 1 ​ ​ 1 ​ ​ 1 } ​ = ​ { ​ f ( ​ n ​ + ​ 1 ​ ) ​ ​ f ( n ) ​ ​ ( n ​ + ​ 1 ) 4 ​ ​ ( n ​ + ​ 1 ) 3 ​ ​ ( n ​ + ​ 1 ) 2 ​ ​ n ​ + ​ 1 ​ ​​ 1 ​ } \small \begin{Bmatrix} \!f(n)\! & \!f(\!n\!-\!1\!)\! & \!n\!^4\! & \!n\!^3\! & \!n\!^2 \!& \!n\! & \!1\! \end{Bmatrix} \begin{Bmatrix} \!1\! & \!1\! & \!0\! & \!0\! & \!0\! & \!0\! & \!0 \\ \!2\! & \!0\! & \!0\! & \!0\! & \!0\! & \!0\! & \!0 \\ \!1\! & \!0\! & \!1\! & \!0\! & \!0\! & \!0\! & \!0 \\ \!4\! & \!0\! & \!4\! & \!1\! & \!0\! & \!0\! & \!0 \\ \!6\! & \!0\! & \!6\! & \!3\! & \!1\! & \!0\! & \!0 \\ \!4\! & \!0\! & \!4\! & \!3\! & \!2\! & \!1\! & \!0 \\ \!1\! & \!0\! & \!1\! & \!1\! & \!1\! & \!1\! & \!1 \end{Bmatrix} \!=\! \begin{Bmatrix} \!f(\!n\!+\!1\!)\! & \!f(n)\! & \!(n\!+\!1)^4\! & \!(n\!+\!1)^3\! & \!(n\!+\!1)^2\! & \!n\!+\!1\! & \!\!1\! \end{Bmatrix} \small {f(n)f(n1)n4n3n2n1}1214641100000000146410001331000012100000110000001={f(n+1)f(n)(n+1)4(n+1)3(n+1)2n+11}
  • 初始向量如下
    { f ( 2 ) f ( 1 ) 16 8 4 2 1 } \begin{Bmatrix} f(2)&f(1)&16&8&4&2&1 \end{Bmatrix} {f(2)f(1)168421}
  • 代码
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

const int MATRIX_SIZE = 7;
const std::int64_t MOD = 2147493647;

struct Matrix {
    std::int64_t data[MATRIX_SIZE][MATRIX_SIZE];

    Matrix() {
        std::memset(data, 0, sizeof(data));
        for (int i = 0; i < MATRIX_SIZE; ++i) {
            data[i][i] = 1L;
        }
    }

    explicit Matrix(const std::int64_t data[][MATRIX_SIZE]) {
        std::memcpy(this->data, data, sizeof(this->data));
    }

    Matrix operator * (const Matrix &matrix) {
        Matrix result;
        std::memset(result.data, 0, sizeof(result.data));
        for (int i = 0; i < MATRIX_SIZE; ++i) {
            for (int j = 0; j < MATRIX_SIZE; ++j) {
                for (int k = 0; k < MATRIX_SIZE; ++k) {
                    result.data[i][j] = result.data[i][j] + ((data[i][k] % MOD) * (matrix.data[k][j] % MOD) % MOD);
                    result.data[i][j] %= MOD;
                }
            }
        }
        return result;
    }
};

struct Vector {
    std::int64_t data[MATRIX_SIZE];

    Vector() {
        std::memset(data, 0, sizeof(data));
    }

    explicit Vector(std::int64_t data[MATRIX_SIZE]) {
        std::memcpy(this->data, data, sizeof(this->data));
    }

    Vector operator * (const Matrix &matrix) {
        Vector result;
        for (int i = 0; i < MATRIX_SIZE; ++i) {
            for (int j = 0; j < MATRIX_SIZE; ++j) {
                result.data[i] += ((data[j] % MOD) * (matrix.data[j][i] % MOD) % MOD);
                result.data[i] %= MOD;
            }
        }
        return result;
    }
};

const std::int64_t matrix_array[][MATRIX_SIZE] {
    1, 1, 0, 0, 0, 0, 0,
    2, 0, 0, 0, 0, 0, 0,
    1, 0, 1, 0, 0, 0, 0,
    4, 0, 4, 1, 0, 0, 0,
    6, 0, 6, 3, 1, 0, 0,
    4, 0, 4, 3, 2, 1, 0,
    1, 0, 1, 1, 1, 1, 1
};

const Matrix mat(matrix_array);

Matrix quick_multiply(Matrix matrix, int n) {
    Matrix result;
    if (n <= 0) {
        return result;
    }
    while (n) {
        if (n & 0x1) {
            result = matrix * result;
        }
        matrix = matrix * matrix;
        n >>= 1;
    }
    return result;
}

int main() {
    int count = 0;
    // std::freopen("build/data.txt", "r", stdin);
    std::int64_t a, b, n;
    std::cin >> count;
    std::int64_t temp[MATRIX_SIZE] = {
        0, 0, 16, 8, 4, 2, 1
    };
    while (count--) {
        std::cin >> n >> temp[1] >> temp[0];
        if (n == 1) {
        	std::cout << temp[1] % MOD << std::endl;
        } else if (n == 2) {
        	std::cout << temp[0] % MOD << std::endl;
        } else {
	        Vector result(temp);
	        result = result * quick_multiply(mat, n - 2);
	        std::cout << result.data[0] << std::endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值