题目描述
大家都知道 数列吧,。
现在问题很简单,输入 和 ,求 的前 项和 。
输入格式
输入 。
输出格式
输出前 项和 。
样例
输入
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; } ```