1. 程式人生 > >矩陣快速冪基礎知識

矩陣快速冪基礎知識

快速冪 CI images 別人 ron 技術分享 blog 是否 img

一、
先介紹以下矩陣的基礎知識
矩陣:有 n 行 m 列組成一個 n*m 的矩陣
1.
矩陣的加減運算
滿足的條件:兩個矩陣的行、列 必須相同
2.
矩陣的乘運算
滿足的條件:
A矩陣的列數為 B矩陣的行數
A(ms)*B(sn)=C(mn)
得到的矩陣 C 是 m 行 n 列的
其中 c[i][j] 為A 的第 i 行與B的第j 列對應乘積的和
即:
技術分享圖片

代碼:

 1 const int N=100;  
 2 int c[N][N];  
 3 void multi(int a[m][s],int b[s][n])//n是矩陣大小,n<N  
 4 {  
 5     memset(c,0
,sizeof c); 6 for(int i=1;i<=m;i++){ 7 for(int j=1;j<=n;j++){ 8 for(int k=1;k<=s;k++){ 9 c[i][j]+=a[i][k]*b[k][j]; 10 c[i][j]%=mod;//一定要在求和之後在 mod 11 } 12 } 13 } 14 }

二、
單位矩陣:
在矩陣的乘法中,有一種矩陣起著特殊的作用,如同數的乘法中的1,這種矩陣被稱為單位矩陣。它是個方陣,從左上角到右下角的對角線(稱為主對角線)上的元素均為1。除此以外全都為0。

簡記: I 或 E
性質:
1、根據矩陣乘法的定義,單位矩陣的重要性質為:
AE=EA=A
2、單位矩陣的特征值皆為1,任何向量都是單位矩陣的特征向量。
3、因為特征值之積等於行列式,所以單位矩陣的行列式為1。因為特征值之和 等於跡數,單位矩陣的跡為 n

技術分享圖片

三、

快速冪的思想:

假設我們要求a^b,最樸素的方法就是不斷地乘a,乘b次,復雜度O(b)。
如果b很大,10^9,就需要用快速冪的思想。
例:a=3,b=100;
100的二進制為:1100100
也就是100可以化成64+32+4。

所以原數可以化成a^64*a^32*a^4

算法流程:
判斷1100100的每一位是否為1,如果是1,就乘對應的二進制次冪。以此類推,直到乘完全部的位數。

時間復雜度O(log n)

 1 /*一般快速冪的模板*/
 2 int quickpow(int a,int b){    
 3     ans=1;     
 4     while(b){    
 5         if(b&1) ans*=a;    
 6         a*=a;    
 7         b>>=1;    
 8     }    
 9     return ans;    
10 }    

(快速冪詳解

https://www.cnblogs.com/wkfvawl/p/9125224.html)

四、

矩陣與DP

a[i]=a[i-1]+b[i-1]+1,b[i]=2*a[i-1]-5 ;a[1]=1,b[1]=1,問a[x]=?,b[x]=?
很簡單的遞推,一步步推即可,但是,如果x是10^9,如何推?
思維:遞推式可以化為矩陣乘積

那麽,矩陣A[i]=A[i-1]*B;
A[i+1]=A[i]*B=A[i-1]*B*B
A[x]=A[1]*B*B*B.......=A[1]*( B^(x-1) );
因為矩陣乘積可以換乘積順序,所以可以先算出B^(x-1),如何計算呢?
快速冪!

問題迎刃而解~

1.構造出遞推矩陣
2.對構造出的矩陣B,進行B^x的快速冪,乘積換成矩陣乘法。
3.最後矩陣的第一行第一列和第二列就是a[x]和a[y]。

其實快速冪和矩陣快速冪是異曲同工,但是往往構造矩陣是難點,轉載一個別人博客寫的矩陣構造方法:

Fibonacci數列:F(0)=1 , F(1)=1 , F(n)=F(n-1)+F(n-2)

我們以前快速求Fibonacci數列第n項的方法是 構造常系數矩陣

(一) Fibonacci數列f[n]=f[n-1]+f[n-2],f[1]=f[2]=1的第n項快速求法(不考慮高精度)

解法:

考慮1×2的矩陣【f[n-2],f[n-1]】。根據Fibonacci數列的遞推關系,我們可以通過乘以一個2×2的矩陣A,得到矩陣:【f[n-1],f[n]】。

即:【f[n-2],f[n-1]】*A = 【f[n-1],f[n]】=【f[n-1],f[n-1]+f[n-2]】

很容易構造出這個2×2矩陣A,即:
0 1
1 1

所以,有【f[1],f[2]】×A=【f[2],f[3]】
又因為矩陣乘法滿足結合律,故有:
【f[1],f[2]】×A ^(n-1) =【f[n],f[n+1]】
這個矩陣的第一個元素f[n]即為所求。

(二) 數列f[n]=f[n-1]+f[n-2]+1,f[1]=f[2]=1的第n項的快速求法(不考慮高精度)

解法:
仿照前例,考慮1×3的矩陣【f[n-2],f[n-1],1】,希望求得某3×3的矩陣A,使得此1×3的矩陣乘以A得到矩陣:【f[n-1],f[n],1】

即:【f[n-2],f[n-1],1】* A =【f[n-1],f[n],1】=【f[n-1],f[n-1]+f[n-2]+1,1】

容易構造出這個3×3的矩陣A,即:
0 1 0
1 1 0
0 1 1

故:【f[1],f[2],1】* A^(n-1) = 【f[n],f[n+1],1】

(三)數列f[n]=f[n-1]+f[n-2]+n+1,f[1]=f[2]=1的第n項的快速求法(不考慮高精度).
解法:
仿照前例,考慮1×4的矩陣【f[n-2],f[n-1],n,1】,希望求得某4×4的矩陣A,使得此1×4的矩陣乘以A得到矩陣:【f[n-1],f[n],n+1,1】
即:【f[n-2],f[n-1],n,1】* A = 【f[n-1],f[n],n+1,1】=【f[n-1],f[n-1]+f[n-2]+n+1,n+1,1】
容易構造出這個4×4的矩陣A,即:
0 1 0 0
1 1 0 0
0 1 1 0
0 1 1 1

故:【f[1],f[2],3,1】* A^(n-1) = 【f[n],f[n+1],n+2,1】

(四) 數列f[n]=f[n-1]+f[n-2],f[1]=f[2]=1的前n項和s[n]=f[1]+f[2]+……+f[n]的快速求法(不考慮高精度).

解法:

仿照之前的思路,考慮1×3的矩陣【f[n-2],f[n-1],s[n-2]】,我們希望通過乘以一個3×3的矩陣A,得到1×3的矩陣:【f[n-1],f[n],s[n-1]】
即:【f[n-2],f[n-1],s[n-2]】 * A = 【f[n-1],f[n],s[n-1]】=【f[n-1],f[n-1]+f[n-2],s[n-2]+f[n-1]】
容易得到這個3×3的矩陣A是:
0 1 0
1 1 1
0 0 1

這種方法的矩陣規模是(r+1)*(r+1)

f(1)=f(2)=s(1)=1 ,所以,有

【f(1),f(2),s(1)】* A = 【f(2),f(3),s(2)】

故:【f(1),f(2),s(1)】* A^(n-1) = 【f(n),f(n+1),s(n)】

(五) 數列f[n]=f[n-1]+f[n-2]+n+1,f[1]=f[2]=1的前n項和s[n]=f[1]+f[2]+……+f[n]的快速求法(不考慮高精度).

解法:

考慮1×5的矩陣【f[n-2],f[n-1],s[n-2],n,1】,
我們需要找到一個5×5的矩陣A,使得它乘以A得到如下1×5的矩陣【f[n-1],f[n],s[n-1],n+1,1】
即:【f[n-2],f[n-1],s[n-2],n,1】* A =【f[n-1],f[n],s[n-1],n+1,1】

=【f[n-1], f[n-1]+f[n-2]+n+1,s[n-2]+f[n-1],n+1,1】
容易構造出A為:
0 1 0 0 0
1 1 1 0 0
0 0 1 0 0
0 1 0 1 0
0 1 0 1 1

故:【f(1),f(2),s(1),3,1】* A^(n-1) = 【f(n),f(n+1),s(n),n+2,1】

一般地,如果有f[n]=p*f[n-1]+q*f[n-2]+r*n+s
可以構造矩陣A為:
0 q 0 0 0
1 p 1 0 0
0 0 1 0 0
0 r 0 1 0
0 s 0 1 1

更一般的,對於f[n]=Sigma(a[n-i]*f[n-i])+Poly(n),其中0<i<=某常數c, Poly (n)表示n的多項式,我們依然可以構造類似的矩陣A來解決問題。
設Degree(Poly(n))=d, 並規定Poly(n)=0時,d=-1,此時對應於常系數線性齊次遞推關系。則本方法求前n項和的復雜度為:
((c+1)+(d+1))3*logns

例如:A(0) = 1 , A(1) = 1 , A(N) = X * A(N - 1) + Y * A(N - 2) (N >= 2);給定三個值N,X,Y求S(N):S(N) = A(0)2 +A(1)2+……+A(n)2。

解:

考慮1*4 的矩陣【s[n-2],a[n-1]^2,a[n-2]^2,a[n-1]*a[n-2]】

我們需要找到一個4×4的矩陣A,使得它乘以A得到1×4的矩陣

【s[n-1],a[n]^2,a[n-1]^2,a[n]*a[n-1]】

即:【s[n-2],a[n-1]^2,a[n-2]^2,a[n-1]*a[n-2]】* A = 【s[n-1],a[n]^2,a[n-1]^2,a[n]*a[n-1]】

= 【s[n-2]+a[n-1]^2 , x^2 * a[n-1]^2 + y^2 * a[n-2]^2 + 2*x*y*a[n-1]*a[n-2] ,

a[n-1]^2 , x*a[n-1]^2 + y*a[n-2]a[n-1]】

可以構造矩陣A為:

1 0 0 0

1 x^2 1 x

0 y^2 0 0

0 2xy 0 y

故:【S[0],a[1]^2,a[0]^2,a[1]*a[0]】 * A^(n-1) = 【s[n-1],a[n]^2,a[n-1]^2,a[n]*a[n-1]】

所以:【S[0],a[1]^2,a[0]^2,a[1]*a[0]】 * A^(n) = 【s[n],a[n+1]^2,a[n]^2,a[n+1]*a[n]】

若A = (B * C ) 則AT = ( B * C )T = CT * BT

技術分享圖片

矩陣快速冪基礎知識