题目描述
推导
题目中给出的公式 $$T(n)=(F_1+2F_2+3F_3+…+nF_n) ······ \ ①$$ $$ F(n) = F(n - 1) + F(n - 2) ······ \ ② $$
我们可以令$$ X_n = nF_n ······ \ ③$$
则$$ T(n) = \sum_{i = 1}^n X_i $$
根据③我们可以写出
$$ X_{n + 1} = (n + 1)F_{n + 1} $$ $$ X_{n + 2} = (n + 2)F_{n + 2} $$
由②
$$ X_{n + 2} = (n + 2)(F_n + F_{n + 1}) $$
即
$$
X_{n + 2} = 2F_n + F_{n + 1} + X_n + X_{n + 1}
$$
在求出$ X_n 、 F_n 、 T_n $ 之间的关系后, 我们就可以构造出一个行向量
$$
G_i =
\begin{pmatrix}
F_i & F_{i + 1} & X_i & X_{i + 1} & T_i
\end{pmatrix}
$$
那么对于下一个向量
$$ G_{i + 1} = \begin{pmatrix} F_{i + 1} & F_{i + 2} & X_{i + 1} & X_{i + 2} & T_{ i + 1} \end{pmatrix} $$
根据以上推导我们就可以写出一个方阵 $ a $,使得
$$ G_i * a = G_{i + 1} $$
$$ a = \begin{pmatrix} 0 & 1 & 0 & 2 & 0 \\\ 1 & 1 & 0 & 1 & 0 \\\ 0 & 0 & 0 & 1 & 0 \\\ 0 & 0 & 1 & 1 & 1 \\\ 0 & 0 & 0 & 0 & 1 \\\ \end{pmatrix} $$
推导结束,剩下的用矩阵乘法和快速幂就可以了。
C++ 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5;
int n, m;
void mul(int c[], int a[], int b[][N])
{
int res[N] = {0};
for(int i = 0; i < N; i ++)
for(int j = 0; j < N; j ++)
res[i] = (res[i] + (ll)a[j] * b[j][i]) % m;
memcpy(c, res, sizeof res);
}
void mul(int c[][N], int a[][N], int b[][N])
{
int res[N][N] = {0};
for(int i = 0; i < N; i ++)
for(int j = 0; j < N; j ++)
for(int k = 0; k < N; k ++)
res[i][j] = (res[i][j] + (ll)a[i][k] * b[k][j]) % m;
memcpy(c, res, sizeof res);
}
void ksm(int res[], int a[][N], int n)
{
while(n)
{
if(n & 1) mul(res, res, a); // res = res * a
mul(a, a, a); // a = a * a;
n >>= 1;
}
}
int main()
{
cin >> n >> m;
// [f(n), f(n + 1), x(n), x(n + 1), t(n)]
int F[N] = {1, 1, 1, 2, 1};
int a[N][N] = {
{0, 1, 0, 2, 0},
{1, 1, 0, 1, 0},
{0, 0, 0, 1, 0},
{0, 0, 1, 1, 1},
{0, 0, 0, 0, 1}
};
ksm(F, a, n - 1);
cout << F[4] << endl;
return 0;
}