矩阵乘法 T3 斐波那契

题目描述

大家都知道 数列吧,

现在问题很简单,输入  和 ,求  的前  项和 

输入格式

输入 

输出格式

输出前  项和 

样例

输入

5 1000

输出

12

数据范围与提示

对于  的数据,

思路

求第 n 项的值时, 可以用矩阵快速幂来求, 把求 转换为 的形式。

定义一个向量 , 求 中满足条件的 。即满足 那么 就是: 所得结果就是 , 而 , 故 满足条件。

因此 就用 来求得, 虽然矩阵乘法不满足交换律, 但满足结合律, 因此可以用快速幂解决。 算 时拆分为 等等。

而这里是让求前 n 项和, 我们需要构造一个能算出答案的矩阵。

考虑把答案也放到向量中, 定义 , 即前 n 项的和, 而 。 构造矩阵 :$$ \begin{bmatrix} 0&1&0 \ 1&1&1 \ 0&0&1 \end{bmatrix}

乘积为 $[f_{n+1}, f_{n}+f_{n+1}, f_{n+1}+S_{n}]$, 而 $S_{n+1} = S_{n} + f_{n+1}$。 最终时间复杂度为 $O(\log n)$。 ## 代码 ```c++ #include <bits/stdc++.h> using namespace std; typedef long long LL; const int N = 3; LL n, m; void mul(LL c[], LL a[], LL b[][N]) { LL temp[N] = {}; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) temp[i] = (temp[i] + (LL)a[j] * b[j][i] % m) % m; memcpy(c, temp, sizeof temp); } void mul(LL c[][N], LL a[][N], LL b[][N]) { LL temp[N][N] = {}; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) for (int k = 0; k < N; k++) temp[i][j] = (temp[i][j] + (LL)a[i][k] * b[k][j] % m) % m; memcpy(c, temp, sizeof temp); } void solve() { cin >> n >> m; LL f1[N] = {1, 1, 1}; LL a[N][N] = { {0, 1, 0}, {1, 1, 1}, {0, 0, 1}}; n--; while (n) { if (n & 1) mul(f1, f1, a); mul(a, a, a); n >>= 1; } cout << f1[2] << endl; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); solve(); return 0; } ```