【题目链接】
【题目考点】
1. 矩阵加速递推
相关知识见:矩阵加速递推模板题
【解题思路】
解法1:转移矩阵为五阶矩阵
构造转移矩阵
已知: T n = F 1 + 2 F 2 + . . . + ( n − 1 ) F n − 1 + n F n T_n=F_1+2F_2+...+(n-1)F_{n-1}+nF_n Tn=F1+2F2+...+(n−1)Fn−1+nFn
所以: T n − 1 = F 1 + . . . + ( n − 1 ) F n − 1 T_{n-1}=F_1+...+(n-1)F_{n-1} Tn−1=F1+...+(n−1)Fn−1
直观考虑可以得到: T n = T n − 1 + n F n T_n=T_{n-1}+nF_n Tn=Tn−1+nFn,但转移矩阵中不可以出现 n n n这样随着递推进行而变化的变量,因此可以考虑将 n F n nF_n nFn作为一个整体看待。
设 G n = n F n G_n=nF_n Gn=nFn,则 T n = T n − 1 + G n T_n=T_{n-1}+G_n Tn=Tn−1+Gn。
该递推式中出现了 G n G_n Gn, G n G_{n} Gn的下一项为 G n + 1 G_{n+1} Gn+1
根据递推式右侧的每一项,在等号左侧都要出现其下一项 ,我们需要写出 G n + 1 G_{n+1} Gn+1的递推式。
G n + 1 = ( n + 1 ) F n + 1 = ( n + 1 ) ( F n + F n − 1 ) = F n + n F n + 2 F n − 1 + ( n − 1 ) F n − 1 = F n + 2 F n − 1 + G n + G n − 1 G_{n+1}=(n+1)F_{n+1}=(n+1)(F_{n}+F_{n-1})\\ =F_n+nF_n+2F_{n-1}+(n-1)F_{n-1}\\ =F_n+2F_{n-1}+G_n+G_{n-1} Gn+1=(n+1)Fn+1=(n+1)(Fn+Fn−1)=Fn+nFn+2Fn−1+(n−1)Fn−1=Fn+2Fn−1+Gn+Gn−1
- 该式右侧出现了 G n − 1 G_{n-1} Gn−1,其下一项为 G n G_n Gn,在等号右侧已经存在。
- 该式右侧出现了 F n F_n Fn, F n F_n Fn的下一项为 F n + 1 F_{n+1} Fn+1,可以写出递推式: F n + 1 = F n + F n − 1 F_{n+1}=F_n+F_{n-1} Fn+1=Fn+Fn−1。 F n F_n Fn与 F n − 1 F_{n-1} Fn−1在等号右侧已经存在。
- 该式右侧出现了 F n − 1 F_{n-1} Fn−1, F n − 1 F_{n-1} Fn−1的下一项为 F n F_n Fn,等号右侧已有了 F n F_n Fn,因此可以写为 F n = F n F_n=F_n Fn=Fn。
整合以上递推式:
T n = 1 ⋅ T n − 1 + 1 ⋅ G n + 0 ⋅ G n − 1 + 0 ⋅ F n + 0 ⋅ F n − 1 T_n = 1\cdot T_{n-1}+1\cdot G_n+0\cdot G_{n-1}+0\cdot F_n+0\cdot F_{n-1} Tn=1⋅Tn−1+1⋅Gn+0⋅Gn−1+0⋅Fn+0⋅Fn−1
G n + 1 = 0 ⋅ T n − 1 + 1 ⋅ G n + 1 ⋅ G n − 1 + 1 ⋅ F n + 2 ⋅ F n − 1 G_{n+1}=0\cdot T_{n-1}+1\cdot G_n+1\cdot G_{n-1}+1\cdot F_n+2\cdot F_{n-1} Gn+1=0⋅Tn−1+1⋅Gn+1⋅Gn−1+1⋅Fn+2⋅Fn−1
G n = 0 ⋅ T n − 1 + 1 ⋅ G n + 0 ⋅ G n − 1 + 0 ⋅ F n + 0 ⋅ F n − 1 G_{n}=0\cdot T_{n-1}+1\cdot G_n+0\cdot G_{n-1}+0\cdot F_n+0\cdot F_{n-1} Gn=0⋅Tn−1+1⋅Gn+0⋅Gn−1+0⋅Fn+0⋅Fn−1
F n + 1 = 0 ⋅ T n − 1 + 0 ⋅ G n + 0 ⋅ G n − 1 + 1 ⋅ F n + 1 ⋅ F n − 1 F_{n+1}=0\cdot T_{n-1}+0\cdot G_n+0\cdot G_{n-1}+1\cdot F_n+1\cdot F_{n-1} Fn+1=0⋅Tn−1+0⋅Gn+0⋅Gn−1+1⋅Fn+1⋅Fn−1
F n = 0 ⋅ T n − 1 + 0 ⋅ G n + 0 ⋅ G n − 1 + 1 ⋅ F n + 0 ⋅ F n − 1 F_{n}=0\cdot T_{n-1}+0\cdot G_n+0\cdot G_{n-1}+1\cdot F_n+0\cdot F_{n-1} Fn=0⋅Tn−1+0⋅Gn+0⋅Gn−1+1⋅Fn+0⋅Fn−1
写成矩阵形式:
T n G n + 1 G n F n + 1 F n = 1 1 0 0 0 0 1 1 1 2 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 T n − 1 G n G n − 1 F n F n − 1 = 1 1 0 0 0 0 1 1 1 2 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 n − 1 T 1 G 2 G 1 F 2 F 1 \begin{bmatrix}T_n\\G_{n+1}\\G_n\\F_{n+1}\\F_n\end{bmatrix}=\begin{bmatrix}1&1&0&0&0\\0&1&1&1&2\\0&1&0&0&0\\0&0&0&1&1\\0&0&0&1&0\end{bmatrix}\begin{bmatrix}T_{n-1}\\G_{n}\\G_{n-1}\\F_{n}\\F_{n-1}\end{bmatrix}=\begin{bmatrix}1&1&0&0&0\\0&1&1&1&2\\0&1&0&0&0\\0&0&0&1&1\\0&0&0&1&0\end{bmatrix}^{n-1}\begin{bmatrix}T_{1}\\G_{2}\\G_{1}\\F_{2}\\F_{1}\end{bmatrix} TnGn+1GnFn+1Fn = 1000011100010000101102010 Tn−1GnGn−1FnFn−1 = 1000011100010000101102010 n−1 T1G2G1F2F1
其中 T 1 = G 1 = F 2 = F 1 = 1 , G 2 = 2 T_1=G_1=F_2=F_1=1, G_2=2 T1=G1=F2=F1=1,G2=2
使用矩阵加速递推算法,即可得到结果 T n T_n Tn。
解法2:转移矩阵为四阶矩阵
已知: T n = F 1 + 2 F 2 + . . . + ( n − 1 ) F n − 1 + n F n T_n=F_1+2F_2+...+(n-1)F_{n-1}+nF_n Tn=F1+2F2+...+(n−1)Fn−1+nFn
如果希望最后的 F n F_n Fn前的系数为常数,可以让 T n T_n Tn减掉 n F n nF_n nFn,顺着这个思路往下想。
设 S n = F 1 + F 2 + . . . + F n S_n=F_1+F_2+...+F_n Sn=F1+F2+...+Fn,那么可以考虑让 n S n nS_n nSn减掉 T n T_n Tn
设 P n = n S n − T n = ( n − 1 ) F 1 + ( n − 2 ) F 2 + . . . + 2 F n − 2 + F n − 1 P_n=nS_n-T_n=(n-1)F_1+(n-2)F_2+...+2F_{n-2}+F_{n-1} Pn=nSn−Tn=(n−1)F1+(n−2)F2+...+2Fn−2+Fn−1
那么 P n − 1 = ( n − 2 ) F 1 + ( n − 3 ) F 2 + . . . + 2 F n − 3 + F n − 2 P_{n-1}=(n-2)F_1+(n-3)F_2+...+2F_{n-3}+F_{n-2} Pn−1=(n−2)F1+(n−3)F2+...+2Fn−3+Fn−2
那么 P n = P n − 1 + F 1 + . . . + F n − 1 = P n − 1 + S n − 1 P_n=P_{n-1}+F_1+...+F_{n-1}=P_{n-1}+S_{n-1} Pn=Pn−1+F1+...+Fn−1=Pn−1+Sn−1
等式右侧出现了 S n − 1 S_{n-1} Sn−1,那么等式左侧需要有 S n S_n Sn
S n = S n − 1 + F n S_n=S_{n-1}+F_n Sn=Sn−1+Fn
等式右侧出现了 F n F_n Fn,等式左侧需要有 F n + 1 F_{n+1} Fn+1
F n + 1 = F n + F n − 1 F_{n+1}=F_n+F_{n-1} Fn+1=Fn+Fn−1
等式右侧出现了 F n − 1 F_{n-1} Fn−1,等式左侧需要有 F n F_n Fn
F n = F n F_n=F_n Fn=Fn
整合上述递推式:
P n = 1 ⋅ P n − 1 + 1 ⋅ S n − 1 + 0 ⋅ F n + 0 ⋅ F n − 1 P_n=1\cdot P_{n-1}+1\cdot S_{n-1}+0\cdot F_n+0\cdot F_{n-1} Pn=1⋅Pn−1+1⋅Sn−1+0⋅Fn+0⋅Fn−1
S n = 0 ⋅ P n − 1 + 1 ⋅ S n − 1 + 1 ⋅ F n + 0 ⋅ F n − 1 S_n=0\cdot P_{n-1}+1\cdot S_{n-1}+1\cdot F_n+0\cdot F_{n-1} Sn=0⋅Pn−1+1⋅Sn−1+1⋅Fn+0⋅Fn−1
F n + 1 = 0 ⋅ P n − 1 + 0 ⋅ S n − 1 + 1 ⋅ F n + 1 ⋅ F n − 1 F_{n+1}=0\cdot P_{n-1}+0\cdot S_{n-1}+1\cdot F_n+1\cdot F_{n-1} Fn+1=0⋅Pn−1+0⋅Sn−1+1⋅Fn+1⋅Fn−1
F n = 0 ⋅ P n − 1 + 0 ⋅ S n − 1 + 1 ⋅ F n + 0 ⋅ F n − 1 F_{n}=0\cdot P_{n-1}+0\cdot S_{n-1}+1\cdot F_n+0\cdot F_{n-1} Fn=0⋅Pn−1+0⋅Sn−1+1⋅Fn+0⋅Fn−1
写出矩阵形式:
P n S n F n + 1 F n = 1 1 0 0 0 1 1 0 0 0 1 1 0 0 1 0 P n − 1 S n − 1 F n F n − 1 = 1 1 0 0 0 1 1 0 0 0 1 1 0 0 1 0 n − 1 P 1 S 1 F 2 F 1 \begin{bmatrix}P_n\\S_n\\F_{n+1}\\F_n\end{bmatrix}=\begin{bmatrix}1&1&0&0\\0&1&1&0\\0&0&1&1\\0&0&1&0\end{bmatrix}\begin{bmatrix}P_{n-1}\\S_{n-1}\\F_n\\F_{n-1}\end{bmatrix}=\begin{bmatrix}1&1&0&0\\0&1&1&0\\0&0&1&1\\0&0&1&0\end{bmatrix}^{n-1}\begin{bmatrix}P_{1}\\S_{1}\\F_2\\F_{1}\end{bmatrix} PnSnFn+1Fn = 1000110001110010 Pn−1Sn−1FnFn−1 = 1000110001110010 n−1 P1S1F2F1
其中 P 1 = S 1 − T 1 = 0 , S 1 = F 2 = F 1 = 1 P_1=S_1-T_1=0, S_1=F_2=F_1=1 P1=S1−T1=0,S1=F2=F1=1
使用矩阵加速递推算法,求出结果矩阵。结果矩阵中包含 P n P_n Pn与 S n S_n Sn。
已知 P n = n S n − T n P_n=nS_n-T_n Pn=nSn−Tn,那么本题结果 T n = ( n S n − P n ) m o d m T_n=(nS_n-P_n)\bmod m Tn=(nSn−Pn)modm
注意: n S n − P n nS_n-P_n nSn−Pn可能为负数,要使用数学取模。
【题解代码】
解法1:转移矩阵为五阶矩阵
cpp
#include<bits/stdc++.h>
using namespace std;
#define N 6
typedef long long LL;
LL n, m;
struct Mat
{
LL n, a[N][N] = {};
Mat(){}
Mat(int _n, int val = 0):n(_n)
{
for(int i = 1; i <= n; ++i)
a[i][i] = val;
}
LL* operator [] (int i)
{
return a[i];
}
Mat operator * (Mat b)
{
Mat r(n);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
for(int k = 1; k <= n; ++k)
r[i][j] = (r[i][j]+a[i][k]*b[k][j])%m;
return r;
}
};
Mat fastPow(Mat a, LL b)
{
Mat r(a.n, 1);
while(b > 0)
{
if(b%2 == 1)
r = r*a;
a = a*a;
b /= 2;
}
return r;
}
int main()
{
cin >> n >> m;
if(n == 1)
cout << 1%m;
else
{
Mat t(5), f(5);
t[1][1] = t[1][2] = t[2][2] = t[2][3] = t[2][4] = t[3][2] = t[4][4] = t[4][5] = t[5][4] = 1, t[2][5] = 2;
f[1][1] = f[3][1] = f[4][1] = f[5][1] = 1, f[2][1] = 2;
Mat r = fastPow(t, n-1)*f;
cout << r[1][1];
}
return 0;
}
解法2:转移矩阵为四阶矩阵
cpp
#include<bits/stdc++.h>
using namespace std;
#define N 5
typedef long long LL;
LL n, m;
struct Mat
{
LL n, a[N][N] = {};
Mat(){}
Mat(int _n, int val = 0):n(_n)
{
for(int i = 1; i <= n; ++i)
a[i][i] = val;
}
LL* operator [] (int i)
{
return a[i];
}
Mat operator * (Mat b)
{
Mat r(n);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
for(int k = 1; k <= n; ++k)
r[i][j] = (r[i][j]+a[i][k]*b[k][j])%m;
return r;
}
};
Mat fastPow(Mat a, LL b)
{
Mat r(4, 1);
while(b > 0)
{
if(b%2 == 1)
r = r*a;
a = a*a;
b /= 2;
}
return r;
}
LL mod(LL a, LL b)
{
return (a%m+b)%m;
}
int main()
{
cin >> n >> m;
if(n == 1)
cout << 1%m;
else
{
Mat t(4), f(4);
t[1][1] = t[1][2] = t[2][2] = t[2][3] = t[3][3] = t[3][4] = t[4][3] = 1;
f[2][1] = f[3][1] = f[4][1] = 1;
Mat r = fastPow(t, n-1)*f;
cout << mod(n*r[2][1]-r[1][1], m);
}
return 0;
}