zoukankan      html  css  js  c++  java
  • 矩阵快速幂

    矩阵快速幂

    1. 什么是矩阵快速幂

    在矩阵加速斐波那契数列中,我们往往需要求这个式子:

    [A^n imes egin{bmatrix} f(1) \ f(0) end{bmatrix} = egin{bmatrix} f(n+1) \ f(n) end{bmatrix} ]

    如何快速的求一个矩阵(A)(k)次幂呢?我们可以使用快速幂。即矩阵快速幂。
    注:本文不涉及基本的线性代数知识。

    2. 算法细节

    我们使用结构体来方便的声明矩阵:

    struct Matrix
    {
    	long long m[N][N];
    }unit;
    

    还需要重载*运算符来执行两个矩阵相乘的操作(Mod 为 1e9 + 7):

    Matrix operator * (const Matrix &x,const Matrix &y)
    {
    	Matrix ans;
    	for(int i = 1;i <= n;i ++ )
    	{
    		for(int j = 1;j <= n;j ++ )
    		{
    			long long t = 0;
    			for(int k = 1;k <= n;k ++ )
    			{
    				t += x.m[i][k] * y.m[k][j] % Mod;
    			}
    			ans.m[i][j] = t % Mod;
    		}
    	}
    	return ans;
    }
    

    重载运算符之后套用快速幂模板得到矩阵快速幂的核心部分:

    Matrix fastM(Matrix a,long long k)
    {
    	Matrix res = unit;
    	
    	while(k)
    	{
    		if(k & 1) res = res * a;
    		a = a * a;
    		k >>= 1;
    	}
    	return res;
    }
    

    你或许会发现上方的代码里有一句:

    Matrix res = unit;
    

    为什么呢?因为unit是一个单位矩阵,unit乘上任何矩阵都等于他本身。即(n imes unit = n)。如果我们不乘以单位矩阵,res将一直为0。
    unit矩阵初始化:

    void init()
    {
    	for(int i = 1; i <= n;i ++ )
    	{
    		unit.m[i][i] = 1;
    	}
    }
    

    3. 完整代码

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 110;
    const int Mod = 1e9 + 7;
    
    long long n,k; 
    
    struct Matrix
    {
    	long long m[N][N];
    }unit;
    
    Matrix operator * (const Matrix &x,const Matrix &y)
    {
    	Matrix ans;
    	for(int i = 1;i <= n;i ++ )
    	{
    		for(int j = 1;j <= n;j ++ )
    		{
    			long long t = 0;
    			for(int k = 1;k <= n;k ++ )
    			{
    				t += x.m[i][k] * y.m[k][j] % Mod;
    			}
    			ans.m[i][j] = t % Mod;
    		}
    	}
    	return ans;
    }
    
    void init()
    {
    	for(int i = 1; i <= n;i ++ )
    	{
    		unit.m[i][i] = 1;
    	}
    }
    
    Matrix fastM(Matrix a,long long k)
    {
    	Matrix res = unit;
    	
    	while(k)
    	{
    		if(k & 1) res = res * a;
    		a = a * a;
    		k >>= 1;
    	}
    	return res;
    }
    
    int main()
    {
    	Matrix a;
    	cin >> n >> k;
    	init();
    	for(int i = 1;i <= n;i ++ )
    	{
    		for(int j = 1;j <= n;j ++ )
    		{
    			cin >> a.m[i][j];
    		}
    	}
    	
    	a = fastM(a,k);
    	
    	for(int i = 1;i <= n;i ++ )
    	{
    		for(int j = 1;j <= n;j ++ )
    		{
    			cout << a.m[i][j] << " ";
    		}
    		cout << endl;
    	}
    	return 0;
    }
    

    矩阵快速幂不难,在理解快速幂的基础上仔细思考就可理解。

    流萤断续光,一明一灭一尺间
  • 相关阅读:
    一秒解决element容器布局显示内部调节框的问题
    操作管理员
    Linux_网络基础管理
    如何解决在WordPress安装Redis插件时需要输入FTP问题?
    如何在我的EC2实例状态更改时获取自定义电子邮件通知
    利用S3fs在Amazon EC2 Linux实例上挂载S3存储桶
    源码安装Apache(httpd)
    Linux_源码安装包管理理论概述
    Linux_yum命令详解
    Linux_yum仓库管理
  • 原文地址:https://www.cnblogs.com/breadcomplex/p/14872124.html
Copyright © 2011-2022 走看看