信息学奥赛一本通 1644:【例 4】佳佳的 Fibonacci

【题目链接】

ybt 1644:【例 4】佳佳的 Fibonacci

【题目考点】

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 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 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; } ```

相关推荐
阿豪只会阿巴12 小时前
【多喝热水系列】从零开始的ROS2之旅——Day5
c++·笔记·python·ubuntu·ros2
郑泰科技12 小时前
fmm(快速地图匹配)实践:Boost header not found解决方案
c++·windows·交通物流
维C泡泡12 小时前
STL(初识string)
开发语言·c++
郝学胜-神的一滴12 小时前
Linux线程使用注意事项:骈文技术指南
linux·服务器·开发语言·数据结构·c++·程序人生
星火开发设计12 小时前
折半插入排序原理与C++实现详解
java·数据结构·c++·学习·算法·排序算法·知识
福楠12 小时前
模拟实现list容器
c语言·开发语言·数据结构·c++·list
lunatic712 小时前
CMake 常用内置变量说明
c++·cmake
程序猿(雷霆之王)13 小时前
C++11——线程库
开发语言·c++
a35354138213 小时前
设计模式-桥接模式
c++·设计模式·桥接模式
panamera1213 小时前
C++ 中 static 关键字
java·开发语言·c++