AcWing 1304. 佳佳的斐波那契

题目链接

\[\begin{aligned}S(n)&=\sum\limits_{i=1}^n F_i\\G(n)&=nF_1+(n-1)F_2+...+F_n=\sum\limits_{i=1}^n(n-i+1)F_i\end{aligned} \]

那么 \(T(n)=nS(n)-G(n-1)\)

那么我们用矩阵加速幂求出 \(S(n)\)\(G(n)\) 即可。

\[\begin{aligned}F_n&=F_{n-1}+F_{n-2}\\S(n)&=S(n-1)+F_n\\G(n)&=G(n-1)+S(n)\end{aligned} \]

再转化一下变为。

\[\begin{aligned}F_n&=F_{n-1}+F_{n-2}\\S(n)&=S(n-1)+F_{n-1}+F_{n-2}\\G(n)&=G(n-1)+S(n-1)+F_{n-1}+F_{n-2}\end{aligned} \]

然后我们设这个矩阵 $$\begin{bmatrix}F_n&F_{n-1}&S(n)&G(n)\end{bmatrix}$$

由此得转置矩阵

\[\begin{bmatrix}1&1&1&1\\1&0&1&1\\0&0&1&1\\0&0&0&1\end{bmatrix} \]

\(\mathscr{Code:}\)

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a, END##i = b; i <= END##i; i++)
#define per(i, a, b) for (int i = a, END##i = b; i >= END##i; i--)
#define DEBUG(x) cerr << #x << " = " << x << '\n'
using LL = long long;
using ULL = unsigned long long;
typedef pair<int, int> PII;

inline LL read() {
    LL s = 0, fu = 1; char ch = getchar();
    while (ch < '0' || ch > '9') ch == '-' ? fu = -1 : 0, ch = getchar();
    while (ch >= '0' && ch <= '9') s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * fu;
}

// const int Mod = 1e9 + 7;
const int Inf = 0x3f3f3f3f;
const LL InfLL = 0x3f3f3f3f3f3f3f3f;

// const int N = 
int n, Mod;
struct Matrix {
    int a[5][5];
    Matrix() {memset(a, 0, sizeof(a));}
    Matrix operator* (const Matrix& b) const {
        Matrix res;
        rep(i, 1, 4) rep(j, 1, 4) rep(k, 1, 4)
            res.a[i][j] = (res.a[i][j] + 1LL * a[i][k] * b.a[k][j]) % Mod;
        return res;
    }
}ans, base, lst;

void qpow(int b) {
    while (b) {
        if (b & 1) ans = ans * base;
        base = base * base;
        b >>= 1;
    }
}

int main() {
    cin >> n >> Mod;
    if (n == 1) {
        printf("%d", 1 % Mod);
        return 0;
    }
    if (n == 2) {
        printf("%d", 3 % Mod);
        return 0;
    }
    ans.a[1][1] = ans.a[1][2] = 1;
    ans.a[1][3] = 2; ans.a[1][4] = 3;
    base.a[1][1] = base.a[1][2] = base.a[1][3] = base.a[1][4] = 1;
    base.a[2][1] = base.a[2][3] = base.a[2][4] = 1;
    base.a[3][3] = base.a[3][4] = 1;
    base.a[4][4] = 1;
    lst = base;
    qpow(n - 3);
    int G = ans.a[1][4];
    ans = ans * lst;
    printf("%d\n", (1LL * n * ans.a[1][3] % Mod - G + Mod) % Mod);
    return 0;
}
posted @ 2025-05-05 16:44  wh2011  阅读(21)  评论(0)    收藏  举报