设斐波那契数列第 k k k 项为 F k F_k F k ,则递推公式:
F k = F k − 1 + F k − 2 F_k=F_{k-1}+F_{k-2}
F k = F k − 1 + F k − 2
则:
[ F k F k − 1 ] = [ 1 1 1 0 ] [ F k − 1 F k − 2 ] \begin{bmatrix}
F_k\\
F_{k-1}
\end{bmatrix}
=
\begin{bmatrix}
1 & 1\\
1 & 0\\
\end{bmatrix}
\begin{bmatrix}
F_{k-1}\\
F_{k-2}
\end{bmatrix}
[ F k F k − 1 ] = [ 1 1 1 0 ] [ F k − 1 F k − 2 ]
则:
[ F k F k − 1 ] = [ 1 1 1 0 ] k − 1 [ F 1 F 0 ] \begin{bmatrix}
F_k\\
F_{k-1}
\end{bmatrix}
=
\begin{bmatrix}
1 & 1\\
1 & 0\\
\end{bmatrix}^{k-1}
\begin{bmatrix}
F_1\\
F_0
\end{bmatrix}
[ F k F k − 1 ] = [ 1 1 1 0 ] k − 1 [ F 1 F 0 ]
那么:
F k = [ 1 1 1 0 ] 1 , 1 k − 1 F_k=\begin{bmatrix}
1 & 1\\
1 & 0\\
\end{bmatrix}^{k-1}_{1,1}
F k = [ 1 1 1 0 ] 1 , 1 k − 1
问题转化为求一个矩阵的 n n n 次幂。
由于矩阵运算满足结合律,我们可以采用矩阵快速幂。
1 2 3 4 5 6 7 8 9 Matrix operator ^ (Matrix A,int k){ Matrix base=A; while (k){ if (k&1 ) base=base*A; A=A*A; k>>=1 ; } return base; }
编写代码如下
1 2 3 4 5 6 7 8 9 10 11 #include <fraction.h> #define Num frac #include <matrix.h> using namespace std;int main () { Matrix A (2 ,2 ) ; A[1 ][1 ]=1 ,A[1 ][2 ]=1 ,A[2 ][1 ]=1 ; for (int i=1 ;i<=10 ;++i){ cout<<"Fib" <<i<<"=" <<(A^(i-1 ))[1 ][1 ]<<endl; } }
如果要求解析解,我们可以采用相似对角化,求出 P P P ,使得 P − 1 A P = Λ P^{-1}AP=\Lambda P − 1 A P = Λ ,则:
A n = ( P Λ P − 1 ) n = P Λ n P − 1 A^n=(P\Lambda P^{-1})^n=P\Lambda^nP^{-1}
A n = ( P Λ P − 1 ) n = P Λ n P − 1
首先,计算特征值:
∣ A − λ E ∣ = 0 |A-\lambda E|=0
∣ A − λ E ∣ = 0
∣ 1 − λ 1 1 − λ ∣ = − λ + λ 2 − 1 \begin{vmatrix}
1-\lambda &1\\
1 &-\lambda\\
\end{vmatrix}
=-\lambda+\lambda^2-1
∣ ∣ ∣ ∣ 1 − λ 1 1 − λ ∣ ∣ ∣ ∣ = − λ + λ 2 − 1
有两个解:
λ 1 = 1 2 + 1 2 5 , λ 2 = 1 2 − 1 2 5 \lambda_1=\frac{1}{2}+\frac{1}{2}\sqrt{5},\lambda_2=\frac{1}{2}-\frac{1}{2}\sqrt{5}
λ 1 = 2 1 + 2 1 5 , λ 2 = 2 1 − 2 1 5
对应 C++ 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Matrix A (2 ,2 ) ;A.Message="A" ; A[1 ][1 ]=1 ,A[1 ][2 ]=1 ,A[2 ][1 ]=1 ; out<<begin_latex ()<<endl<<endl; out<<to_latex (A)<<endl<<endl; Matrix B=A; for (int i=1 ;i<=A.row;++i){ B[i][i]=B[i][i]-Num ("l" ); } cout<<"Eigen Poly" <<endl; _poly x=Determinant (B).x; cout<<x<<endl; out<<to_latex (B,"vmatrix" )<<"=" <<to_latex (x)<<endl<<endl; upoly _x; _x.init_from_poly (x); cpoly v=Factorization (_x); v.sort (); cout<<"Factorization" <<endl<<v<<endl; out<<"Factorize it then we have " <<to_latex (v)<<endl<<endl;
对于每一个特征值,用基础解系求得一个特征向量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 for (int i=0 ;i<v.v.size ();++i){ if (v.v[i].first.deg ()==1 ){ Num lambda=poly (poly_ele ((frac)(0 )-v.v[i].first[0 ])); out<<"For eigen value $\\lambda=" <<to_latex (lambda,0 )<<"$ ,we have vectors," <<endl<<endl; cout<<"lambda=" <<lambda<<endl; cout<<"n=" <<v.v[i].second<<endl; Matrix B=A-lambda*Matrix (A.row,A.col,1 ); vector<Matrix>baseS=baseSolution (B); cout<<"m=" <<baseS.size ()<<endl; cout<<B<<endl; for (int i=0 ;i<baseS.size ();++i){ cout<<baseS[i]<<endl; s.push_back (baseS[i]); out<<to_latex (baseS[i])<<endl<<endl; } } else if (v.v[i].first.deg ()==2 ){ Num lambda_1,lambda_2; frac a=v.v[i].first[2 ],b=v.v[i].first[1 ],c=v.v[i].first[1 ]; frac delta=b*b-4 *a*c; lambda_1=poly_ele (sqrtNum (-b/(2 *a),1 /(2 *a),delta)); lambda_2=poly_ele (sqrtNum (-b/(2 *a),-1 /(2 *a),delta)); out<<"For eigen value $\\lambda=" <<to_latex (lambda_1,0 )<<"$ ,we have vectors," <<endl<<endl; cout<<"lambda=" <<lambda_1<<endl; cout<<"n=" <<v.v[i].second<<endl; Matrix B=A-lambda_1*Matrix (A.row,A.col,1 ); vector<Matrix>baseS=baseSolution (B); cout<<"m=" <<baseS.size ()<<endl; cout<<B<<endl; for (int i=0 ;i<baseS.size ();++i){ cout<<baseS[i]<<endl; s.push_back (baseS[i]); out<<to_latex (baseS[i])<<endl<<endl; } out<<"For eigen value $\\lambda=" <<to_latex (lambda_2,0 )<<"$ ,we have vectors," <<endl<<endl; cout<<"lambda=" <<lambda_2<<endl; cout<<"n=" <<v.v[i].second<<endl; B=A-lambda_2*Matrix (A.row,A.col,1 ); baseS=baseSolution (B); cout<<"m=" <<baseS.size ()<<endl; cout<<B<<endl; for (int i=0 ;i<baseS.size ();++i){ cout<<baseS[i]<<endl; s.push_back (baseS[i]); out<<to_latex (baseS[i])<<endl<<endl; } } }
得到:
η 1 = [ 1 2 + 1 2 5 1 ] , η 2 = [ 1 2 − 1 2 5 1 ] \eta_1=\begin{bmatrix}
\frac{1}{2}+\frac{1}{2}\sqrt{5}\\
1\\
\end{bmatrix},\eta_2=\begin{bmatrix}
\frac{1}{2}-\frac{1}{2}\sqrt{5}\\
1\\
\end{bmatrix}
η 1 = [ 2 1 + 2 1 5 1 ] , η 2 = [ 2 1 − 2 1 5 1 ]
组合形成
P = [ 1 2 + 1 2 5 1 2 − 1 2 5 1 1 ] P=\begin{bmatrix}
\frac{1}{2}+\frac{1}{2}\sqrt{5} &\frac{1}{2}-\frac{1}{2}\sqrt{5}\\
1 &1\\
\end{bmatrix}
P = [ 2 1 + 2 1 5 1 2 1 − 2 1 5 1 ]
且:
Λ = P A P − 1 = [ 1 2 + 1 2 5 0 0 1 2 − 1 2 5 ] \Lambda=PAP^{-1}=\begin{bmatrix}
\frac{1}{2}+\frac{1}{2}\sqrt{5} &0\\
0 &\frac{1}{2}-\frac{1}{2}\sqrt{5}\\
\end{bmatrix}
Λ = P A P − 1 = [ 2 1 + 2 1 5 0 0 2 1 − 2 1 5 ]
解得:
F n = ( 1 2 + 1 10 5 ) ( 1 2 + 1 2 5 ) n − 1 + ( 1 2 − 1 10 5 ) ( 1 2 − 1 2 5 ) n − 1 F_n=(\frac{1}{2}+\frac{1}{10}\sqrt{5})(\frac{1}{2}+\frac{1}{2}\sqrt{5})^{n-1}+(\frac{1}{2}-\frac{1}{10}\sqrt{5})(\frac{1}{2}-\frac{1}{2}\sqrt{5})^{n-1}
F n = ( 2 1 + 1 0 1 5 ) ( 2 1 + 2 1 5 ) n − 1 + ( 2 1 − 1 0 1 5 ) ( 2 1 − 2 1 5 ) n − 1
对应代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Matrix P=s[0 ]; out<<"Combine the vectors together then we get, " <<endl<<endl; for (int i=1 ;i<s.size ();++i){ P=addH (P,s[i]); } cout<<P.message ("P" )<<endl; cout<<(P^(-1 )).message ("P^{-1}" )<<endl; cout<<((P^-1 )*A*P).message ("P^{-1}AP" )<<endl; Matrix Lambda=(P^-1 )*A*P; out<<to_latex (P.message ("P" ))<<endl<<endl; out<<to_latex (((P^-1 )*A*P).message ("\\Lambda=PAP^{-1}" ))<<endl<<endl; out<<"So $A^n=P^{-1}\\Lambda^n P$" <<endl<<endl; out<<"For calculating $A^n$, assume $\\Lambda^n$=[a,0;0,b], then we have:" <<endl<<endl; Matrix _A(2 ,2 ); _A[1 ][1 ]=poly ("a" ),_A[2 ][2 ]=poly ("b" ); cout<<P*_A*(P^-1 )<<endl; out<<to_latex ((P*_A*(P^-1 ))[1 ][1 ])<<endl<<endl; out<<"Then, substitute $a=(" <<to_latex (Lambda[1 ][1 ],0 )<<")^{n-1}$ and $b=(" <<to_latex (Lambda[2 ][2 ],0 )<<")^{n-1}$, we have the final answer" <<endl<<endl;
一些小小的推广
求 F k = F k − 1 + 2 F k − 2 F_k=F_{k-1}+2F_{k-2} F k = F k − 1 + 2 F k − 2 的通项。
则:
A = [ 1 2 1 0 ] A=\begin{bmatrix}1&2\\1 &0\end{bmatrix}
A = [ 1 1 2 0 ]
利用程序自动生成结果:
求 F k = − 2 F k − 1 + F k − 2 + 2 F k − 3 F_k=-2F_{k-1}+F_{k-2}+2F_{k-3} F k = − 2 F k − 1 + F k − 2 + 2 F k − 3 的通项。
则:
A = [ − 2 1 2 1 0 0 0 1 0 ] A=\begin{bmatrix}
-2 &1 &2\\
1 &0 &0\\
0 &1 &0\\
\end{bmatrix}
A = ⎣ ⎡ − 2 1 0 1 0 1 2 0 0 ⎦ ⎤
注意到,程序算出的 A A A 的特征多项式就是我们常说的数列的特征多项式,在后面严格证明。
更进一步推广:常系数齐次线性递推
一个 k k k 阶常系数齐次递推数列满足:
f n = ∑ i = 1 k a i f n − i f_n=\sum_{i=1}^ka_if_{n-i}
f n = i = 1 ∑ k a i f n − i
对于斐波那契数列:
a 1 = a 2 = 1 a_1=a_2=1
a 1 = a 2 = 1
转移矩阵:
A = ( a 1 a 2 a 3 … a k − 2 a k − 1 a k 1 0 0 … 0 0 0 0 1 0 ⋯ 0 0 0 ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ ⋮ 0 0 0 ⋯ 1 0 0 0 0 0 ⋯ 0 1 0 ) A=\begin{pmatrix}a_1&a_2&a_3&\dots&a_{k-2}&a_{k-1}&a_k\\1&0&0&\dots&0&0&0\\0&1&0&\cdots&0&0&0\\\vdots&\vdots&\vdots&\ddots&\vdots&\vdots&\vdots\\0&0&0&\cdots&1&0&0\\0&0&0&\cdots&0&1&0\end{pmatrix}
A = ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ a 1 1 0 ⋮ 0 0 a 2 0 1 ⋮ 0 0 a 3 0 0 ⋮ 0 0 … … ⋯ ⋱ ⋯ ⋯ a k − 2 0 0 ⋮ 1 0 a k − 1 0 0 ⋮ 0 1 a k 0 0 ⋮ 0 0 ⎠ ⎟ ⎟ ⎟ ⎟ ⎟ ⎟ ⎟ ⎞
初值:
F = ( f k − 1 f k − 2 ⋮ f 0 ) F=\begin{pmatrix}f_{k-1}\\f_{k-2}\\\vdots\\f_0\end{pmatrix}
F = ⎝ ⎜ ⎜ ⎜ ⎛ f k − 1 f k − 2 ⋮ f 0 ⎠ ⎟ ⎟ ⎟ ⎞
则答案变成 ( A n F ) k , 1 (A^nF)_{k,1} ( A n F ) k , 1 。还是转化为计算 A n A^n A n 。
不妨设多项式
g ( λ ) = ∣ λ E − A ∣ g(\lambda)=|\lambda E-A|
g ( λ ) = ∣ λ E − A ∣
在第一行第一列展开,我们得到 λ k \lambda^k λ k ,在第一行第二列展开,我们得到 − λ k − 1 a 1 -\lambda^{k-1}a_1 − λ k − 1 a 1 ,在第一行第三列展开,我们得到 − λ k − 2 a 2 -\lambda^{k-2}a_2 − λ k − 2 a 2 ,之后一直到 − λ 0 a k -\lambda^0a_k − λ 0 a k 。
于是
g ( λ ) = λ k − a 1 λ k − 1 − ⋯ − a k g(\lambda)=\lambda^k-a_1\lambda^{k-1}-\cdots-a_k
g ( λ ) = λ k − a 1 λ k − 1 − ⋯ − a k
由 Cayley-Hamilton 定理,我们也知道 g ( A ) = 0 g(A)=0 g ( A ) = 0 ,那么我们希望凑出 g ( A ) g(A) g ( A ) 的形式,就可以进行抵消。
不妨设 A n = f ( A ) g ( A ) + r ( A ) A^n=f(A)g(A)+r(A) A n = f ( A ) g ( A ) + r ( A ) ,其中 f , r f,r f , r 都是关于 A A A 的多项式。那么就可以转化为多项式除法和取余的问题。答案是 r ( A ) r(A) r ( A ) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <poly.h> #define Num frac #include <matrix.h> #define MAXN 1005 using namespace std;frac a[MAXN]; int main () { int n,k; cin>>n>>k; upoly g; g.v.resize (k+1 ); g[k]=frac (1 ); for (int i=1 ;i<=k;++i){ cin>>a[i]; g[k-i]=-a[i]; } Matrix A (k,k) ; for (int i=1 ;i<=k;++i) A[1 ][i]=a[i]; for (int i=1 ;i<=k-1 ;++i) A[i+1 ][i]=1 ; upoly M; M.v.resize (n+1 ); M[n]=frac (1 ); upoly r=M%g; Matrix An=Matrix (k,k); for (int i=r.v.size ()-1 ;i>=0 ;--i) An=An*A+r.v[i]*Matrix (k,k,1 ); Matrix F (k,1 ) ; for (int i=1 ;i<=k;++i) cin>>F[k-i+1 ][1 ]; cout<<(An*F)[k][1 ]<<endl; }
例如,计算 f i b 8 fib_{8} f i b 8 ,则输入
不用线性代数的另解:生成函数
构造f ( x ) = ∑ j = 1 f i b j x j f(x)=\sum _{j=1} fib_j x^j f ( x ) = ∑ j = 1 f i b j x j
所以f ( x ) × x = ∑ j = 2 f i b j − 1 x j f(x) \times x=\sum_{j=2} fib_{j-1}x^j f ( x ) × x = ∑ j = 2 f i b j − 1 x j
f ( x ) − f ( x ) × x = f i b 1 x + ∑ j = 3 f i b j − 2 x j = x + x 2 × f ( x ) f(x)-f(x)\times x=fib_1x+\sum_{j=3}^{}fib_{j-2}x^j=x+x^2\times f(x) f ( x ) − f ( x ) × x = f i b 1 x + ∑ j = 3 f i b j − 2 x j = x + x 2 × f ( x )
所以f ( x ) = x 1 − x − x 2 f(x)=\frac{x}{1-x-x^2} f ( x ) = 1 − x − x 2 x
令ϕ = 1 + 5 2 , ϕ ′ = 1 − 5 2 \phi =\frac{1+\sqrt{5}}{2},\phi'=\frac{1-\sqrt{5}}{2} ϕ = 2 1 + 5 , ϕ ′ = 2 1 − 5 。
分解:x 1 − x − x 2 = x ( 1 − ϕ ′ x ) ( 1 − ϕ x ) = 1 5 ( 1 1 − ϕ x − 1 1 − ϕ ′ x ) \frac{x}{1-x-x^2}=\frac{x}{(1-\phi'x)(1-\phi x)}=\frac{1}{\sqrt{5}}(\frac{1}{1-\phi x} - \frac{1}{1-\phi' x}) 1 − x − x 2 x = ( 1 − ϕ ′ x ) ( 1 − ϕ x ) x = 5 1 ( 1 − ϕ x 1 − 1 − ϕ ′ x 1 )
根据公式1 1 − x = ∑ j = 0 x j \frac{1}{1-x}=\sum _{j=0} x^{j} 1 − x 1 = ∑ j = 0 x j ,前面一项化为( ϕ ) n (\phi)^n ( ϕ ) n 后面一项化成( ϕ ′ ) n (\phi')^n ( ϕ ′ ) n 。
于是我们得到f i b n = 1 5 ( ϕ n − ϕ ′ n ) fib_n=\frac{1}{\sqrt{5}}(\phi ^n-\phi'^n) f i b n = 5 1 ( ϕ n − ϕ ′ n ) 。
即f i b n = − 1 5 ( 1 − 5 2 ) n + 1 5 ( 1 + 5 2 ) n fib_n=-\frac{1}{\sqrt 5}(\frac{1-\sqrt 5}{2})^n+\frac{1}{\sqrt 5}(\frac{1+\sqrt 5}{2})^n f i b n = − 5 1 ( 2 1 − 5 ) n + 5 1 ( 2 1 + 5 ) n 。