HDU - 5950 Recursive sequence(非常规矩阵快速幂)

传送门


题目大意

给出一个如下的递推式,给出前两项求第 n n n项:

f ( n ) = f ( n − 1 ) + 2 f ( n − 2 ) + n 4 f(n)=f(n-1)+2f(n-2)+n^4 f(n)=f(n1)+2f(n2)+n4

解题思路

对于 n 4 n^4 n4,实际上和 f ( n ) f(n) f(n)并不是递推关系,一开始想的是将 n 4 n^4 n4和前面部分拆开来求,但是这样是错误的,不能拆开,因此考虑以下思路:

n 4 = [ ( n − 1 ) + 1 ] 4 = C 4 0 ( n − 1 ) 4 + C 4 1 ( n − 1 ) 3 + C 4 2 ( n − 1 ) 2 + C 4 1 ( n − 1 ) + 1 n^4=[(n-1)+1]^4 = C_4^0(n-1)^4+C_4^1(n-1)^3+C_4^2(n-1)^2+C_4^1(n-1)+1 n4=[(n1)+1]4=C40(n1)4+C41(n1)3+C42(n1)2+C41(n1)+1

那么有 f ( n ) = f ( n − 1 ) + 2 f ( n − 2 ) + C 4 0 ( n − 1 ) 4 + C 4 1 ( n − 1 ) 3 + C 4 2 ( n − 1 ) 2 + C 4 1 ( n − 1 ) + 1 f(n)=f(n-1)+2f(n-2)+C_4^0(n-1)^4+C_4^1(n-1)^3+C_4^2(n-1)^2+C_4^1(n-1)+1 f(n)=f(n1)+2f(n2)+C40(n1)4+C41(n1)3+C42(n1)2+C41(n1)+1

对于这个东西,我们首先设 X n − 1 = [ f ( n − 1 ) f ( n − 2 ) ( n − 1 ) 4 ( n − 1 ) 3 ( n − 1 ) 2 ( n − 1 ) 1 1 ] X_{n-1}=\left[ \begin{array}{ccc} f(n-1) \\ f(n-2) \\ (n-1)^4 \\ (n-1)^3 \\(n-1)^2 \\ (n-1)^1 \\ 1 \end{array} \right] Xn1=f(n1)f(n2)(n1)4(n1)3(n1)2(n1)11

那么不难得出 X n = [ f ( n ) f ( n − 1 ) n 4 n 3 n 2 n 1 1 ] X_{n}=\left[ \begin{array}{ccc} f(n) \\ f(n-1) \\ n^4 \\ n^3 \\ n^2 \\ n^1 \\ 1 \end{array} \right] Xn=f(n)f(n1)n4n3n2n11

考虑构造出一个 7 × 7 7 \times 7 7×7的方阵 m m m使得 X n = m ∗ X n − 1 X_n = m*X_{n-1} Xn=mXn1,我们可以首先假设所有项都为未知数,然后根据矩阵乘法的规律,可以求出每一项,最后可以得到:

m = [ 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 ] m = \left[ \begin{array}{ccc} 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\end{array} \right] m=1100000200000010100004041000606310040432101011111

那么最后的递推矩阵式为:

[ f ( n ) f ( n − 1 ) n 4 n 3 n 2 n 1 1 ] = [ 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 ] n − 2 [ f ( 2 ) f ( 1 ) 2 4 2 3 2 2 2 1 1 ] \left[ \begin{array}{ccc} f(n) \\ f(n-1) \\ n^4 \\ n^3 \\ n^2 \\ n^1 \\ 1 \end{array} \right] = \left[ \begin{array}{ccc} 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\end{array} \right]^{n-2} \left[ \begin{array}{ccc} f(2) \\ f(1) \\ 2^4 \\ 2^3 \\ 2^2 \\ 2^1 \\ 1 \end{array} \right] f(n)f(n1)n4n3n2n11=1100000200000010100004041000606310040432101011111n2f(2)f(1)242322211

代码
//
// Created by Happig on 2020/10/25
//
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>

using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define ENDL "\n"
#define lowbit(x) (x&(-x))
#define mkp(x, y) make_pair(x,y)
#define mem(a, x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const ll Mod = 2147493647;
const int maxn = 2e5 + 10;

const int arr1[10][10] = {{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}};
int arr2[] = {0, 0, (1 << 4), (1 << 3), (1 << 2), (1 << 1), 1};

struct Matrix {
    ll matrix[10][10];
    int n, m;

    Matrix() {}

    Matrix(int x, int y) {
        n = x, m = y;
        memset(matrix, 0, sizeof(matrix));
    }
};

Matrix mul(Matrix a, Matrix b) {
    Matrix ans(a.n, b.m);
    for (int i = 1; i <= ans.n; i++) {
        for (int j = 1; j <= ans.m; j++) {
            for (int k = 1; k <= a.m; k++) {
                ans.matrix[i][j] += a.matrix[i][k] * b.matrix[k][j] % Mod;
                ans.matrix[i][j] %= Mod;
            }
        }
    }
    return ans;
}

Matrix qkp(Matrix mx, ll n) {
    Matrix ans(mx.n, mx.m);
    for (int i = 1; i <= mx.n; i++) ans.matrix[i][i] = 1;
    while (n) {
        if (n & 1) ans = mul(ans, mx);
        mx = mul(mx, mx);
        n >>= 1;
    }
    return ans;
}

ll solve(ll n) {
    if (n == 1) return arr2[1];
    if (n == 2) return arr2[0];
    Matrix mx(7, 7);
    for (int i = 1; i <= 7; i++) {
        for (int j = 1; j <= 7; j++) {
            mx.matrix[i][j] = arr1[i - 1][j - 1];
        }
    }
    Matrix dw(7, 1);
    for (int i = 1; i <= 7; i++) {
        dw.matrix[i][1] = arr2[i - 1];
    }
    Matrix ans = mul(qkp(mx, n - 2), dw);
    return ans.matrix[1][1];
}

int main() {
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, T;
    cin >> T;
    while (T--) {
        cin >> n >> arr2[1] >> arr2[0];
        cout << solve(n) << endl;
    }
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值