矩陣快速冪

BY 賴浩瑋

  • 矩陣乘法
  • 快速冪

what is矩陣快速冪

  • 求一種將兩個m×p和n×p矩陣相乘的方法(?)
  • 定義:Cij=  Aik×Bik
  • 更具體點 : http://matrixmultiplication.xyz
  • 複雜度:O(n³)

 

  •  

 

  •  
  •  
  •  

 

 

矩陣乘法

code

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define length 3
struct matrix {
    long long mat[length][length];
    void init(){
        memset(mat,0,sizeof(mat));
    };
};
matrix mul(matrix a, matrix b)
{
    matrix c;
    c.init();
    for(int j=0 ; j<length ; j++)
     {
         for(int i=0; i<length ; i++)
         {
             for(int m=0; m<length ; m++)
             {
                c.mat[j][i]+=a.mat[j][m]*b.mat[m][i];
              
             }
         }
     }
    return c;
};

int main()
{
    matrix a,b;
    a.init();
    b.init();
    for(int i=0; i<length ; i++)for(int j=0 ; j<length ;j++)cin >> a.mat[i][j];
    for(int i=0; i<length ; i++)for(int j=0 ; j<length ;j++)cin >> b.mat[i][j];
    matrix c = mul(a,b);
    
    for(int i=0 ; i<length ;i++)
    {
        for(int j=0 ; j<length ; j++)
        {
            cout << c.mat[i][j] << ' ' ;
        }
        cout << endl;
    }
    
    return 0;
}

簡單來說,我們將a轉換成二進位在做運算就能實現將本來O(n³)的巨無霸變成O(n)的聰明算法

快速冪

  • &:確認a是否為2ⁿ的工具
  • >>:將二進位表示法右移

工具

我們可以用2ⁿ表示出任何數字,比如說15=1×2⁰+1×2¹+1×2²+1×2³,在將其表述成1111

what is 二進位

  1. 先將a變成二進位表示
  2. 檢視他究竟2ⁿ這項是不是有
  3. 如果有就將他乘上去

做法

#include <bits/stdc++.h>
using namespace std;

int main() {
	int n,a;
	int ans=1;
	cin >> a >> n;
	while(n > 0)
	{
	if(n & 1==1) ans=(ans*a);
	n = n >> 1;
	a=(a*a);
	}
	cout << ans <<endl; 
			
	
		
	return 0;
}

code

 

​我們可以用費氏數列舉例

 

what is 矩陣快速冪

  • 費氏數列是由義大利數學家費波那契所提出的一串數字,聽說很神奇(?

何謂費氏數列

f(n) = f(n-2) + f(n-1)

遞迴式

#include<bits/stdc++.h>

using namespace std;

#define ll long long
#define length 2 

struct matrix
{
    ll mat[2][2];    
};
struct matrix mul(struct matrix A, struct matrix B)
{
    struct matrix C;
     C.mat[0][0]=C.mat[0][1]=C.mat[1][0]=C.mat[1][1]=0;
    
    for (int i=0; i<length; i++)
        for (int j=0; j<length; j++)
            for (int k=0; k<length; k++)
                C.mat[i][j]+=A.mat[i][k]*B.mat[k][j];
    return C;
}
struct matrix fastPow(struct matrix A, int n)
{
    struct matrix I; // identity matrix
    I.mat[0][0]=I.mat[1][1]=1;
    I.mat[0][1]=I.mat[1][0]=0;
    
    while (n!=0)
    {
        if (n&1)
        {
            I=mul(I, A);
        }
        A=mul(A, A);
        n>>=1;
    }
        return I;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
  
    int n=0;
    
    while (cin >> n)
    {
        struct matrix A; // A: {[0, 1], [1, 1]}
        struct matrix B; // B: {[0, not used], [1, not used]}
        
        A.mat[0][0]=0;
        A.mat[0][1]=1;
        A.mat[1][0]=1;
        A.mat[1][1]=1;
        B.mat[0][0]=0; // f0
        B.mat[0][1]=0;
        B.mat[1][0]=1; // f1
        B.mat[1][1]=0;
        
        struct matrix ans;
        
        ans=fastPow(A, n);
        
        cout << ans.mat[1][0] << endl;
    }

    return 0;
}
Made with Slides.com