矩阵的应用

一.矩阵的基本运算

加减法:直接进行加减法即可

乘法:对每一行和每一列取乘积和

转置:将矩阵倒置并逆时针旋转90度

 

二.矩阵的初等变换

1.两行(列)互换

2.某行(列)乘上非零系数

3.某行(列)乘上常数后加到另一行(列)上

 

三.经典应用

1.求A到B,恰好经过k个点的路径数量

 

HDU2157

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 39+7,mod = 1e3;
int n,m,T;
struct matrix{ll mat[N][N];};
matrix operator *(const matrix &a,const matrix &b){matrix c;memset(c.mat,0,sizeof(c.mat));for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){for(int k=1;k<=n;k++){c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;}}}return c;
}
matrix quickPow(matrix a,ll b){matrix ans;memset(ans.mat,0,sizeof(ans.mat));for(int i=1;i<=n;i++)ans.mat[i][i]=1;while(b){if(b&1)ans=ans*a;a=a*a;b>>=1;}return ans;
}
int main(){while(cin>>n>>m){if(!n&&!m)break;matrix a;memset(a.mat,0,sizeof(a.mat));for(int i=1;i<=m;i++){int x,y;cin>>x>>y;x++,y++;a.mat[x][y]=1;}cin>>T;while(T--){int x,y,k;cin>>x>>y>>k;x++,y++;matrix p=quickPow(a,k);cout<<p.mat[x][y]<<'\n';}}	return 0;
}

 技巧:巧妙的运用了矩阵乘法的运算,将其转化为计算路径条数的方式

2.给定矩阵A,求A + A^2 + A^3 + … + A^k的结果

POJ3233

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int N = 39+7;
int n,mod,k;
struct matrix{ll mat[N][N];}a;
matrix operator *(const matrix &a,const matrix &b){matrix c;memset(c.mat,0,sizeof(c.mat));for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){for(int k=1;k<=n;k++){c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;}}}return c;
}
matrix operator +(const matrix &a,const matrix &b){matrix c;memset(c.mat,0,sizeof(c.mat));for(int i=0;i<N;i++){for(int j=0;j<N;j++){c.mat[i][j]=(a.mat[i][j]+b.mat[i][j])%mod;}}return c;
}
matrix quickPow(matrix a,ll b){matrix ans;memset(ans.mat,0,sizeof(ans.mat));for(int i=1;i<=n;i++)ans.mat[i][i]=1;while(b){if(b&1)ans=ans*a;a=a*a;b>>=1;}return ans;
}
matrix solve(int k){if(k==1)return a;if(k%2==1){matrix pp=solve(k/2);matrix qq=quickPow(a,k); matrix ans=pp+quickPow(a,k/2)*pp+qq;return ans;}matrix pp=solve(k/2);matrix ans=pp+(quickPow(a,k/2)*pp);return ans;
}
int main(){cin>>n>>k>>mod;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>a.mat[i][j];}} matrix p=solve(k);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cout<<p.mat[i][j]<<' ';}puts("");}return 0;
}

  

 

技巧:运用分治和矩阵的分配律,在O(logk)的复杂度内求解完问题

 

3.给定n和p,求第n个Fibonacci数mod p的值,n不超过2^63

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3,mod = 1e9+7;
struct matrix{ll mat[N][N];};
matrix operator *(const matrix &a,const matrix &b){matrix c;memset(c.mat,0,sizeof(c.mat));for(int i=1;i<N;i++){for(int j=1;j<N;j++){for(int k=1;k<N;k++){c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;}}}return c;
}
matrix quickPow(matrix a,ll b){matrix ans;memset(ans.mat,0,sizeof(ans.mat));for(int i=1;i<N;i++)ans.mat[i][i]=1;while(b){if(b&1)ans=ans*a;a=a*a;b>>=1;}return ans;
}
int main(){ll n;cin>>n;if(n<=2){cout<<1<<'\n';return 0;}matrix a;memset(a.mat,0,sizeof(a.mat));a.mat[1][1]=a.mat[1][2]=1;matrix p;memset(p.mat,0,sizeof(p.mat));p.mat[1][1]=p.mat[1][2]=p.mat[2][1]=1;a=a*quickPow(p,n-2);cout<<a.mat[1][1]<<'\n';return 0;
}

  

技巧:巧妙地使用矩阵快速幂加速递推,复杂度O(logn)

 

4.给定一个递推式,要求在O(logn)复杂度内求解

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 4,mod = 1e9+7;
struct matrix{ll mat[N][N];};
matrix operator *(const matrix &a,const matrix &b){matrix c;memset(c.mat,0,sizeof(c.mat));for(int i=1;i<N;i++){for(int j=1;j<N;j++){for(int k=1;k<N;k++){c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;}}}return c;
}
matrix quickPow(matrix a,ll b){matrix ans;memset(ans.mat,0,sizeof(ans.mat));for(int i=1;i<N;i++)ans.mat[i][i]=1;while(b){if(b&1)ans=ans*a;a=a*a;b>>=1;}return ans;
}
int main(){int T;cin>>T;while(T--){int n;cin>>n;if(n<=3){cout<<1<<'\n';continue;}matrix a;memset(a.mat,0,sizeof(a.mat));a.mat[1][1]=a.mat[1][2]=a.mat[1][3]=1;matrix p;memset(p.mat,0,sizeof(p.mat));p.mat[1][1]=p.mat[1][3]=p.mat[2][1]=p.mat[3][2]=1;a=a*quickPow(p,n-3);cout<<a.mat[1][1]<<'\n';}return 0;
}

  技巧:和斐波那契数列一样,巧妙地使用矩阵快速幂加速递推,复杂度O(logn)

 

5.高斯消元

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e2+39+7;
int n;double a[N][N];
int gauss(){for(int i=1;i<=n;i++){int r=n+1;for(int j=i;j<=n;j++)if(fabs(a[j][i])>fabs(a[(r==n+1?0:r)][i]))r=j;if(r==n+1)return -1;//		int r=i;
//		for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>fabs(a[r][i]))r=j;
//		cout<<i<<' '<<r<<'\n';for(int j=1;j<=n+1;j++)swap(a[i][j],a[r][j]);if(fabs(a[i][i])<(1e-7))return 0;for(int j=n+1;j>=1;j--)a[i][j]/=a[i][i];for(int j=1;j<=n;j++){if(i==j)continue;double m=a[j][i]/a[i][i];for(int k=1;k<=n+1;k++)a[j][k]-=a[i][k]*m;}}return 1;
}
int main(){cin>>n;for(int i=1;i<=n+1;i++)a[0][i]=0;for(int i=1;i<=n;i++){for(int j=1;j<=n+1;j++){cin>>a[i][j];}}int k=gauss();if(k==1)for(int i=1;i<=n;i++)printf("x%d=%.2lf\n",i,a[i][n+1]);else if(k==-1)cout<<"0";else cout<<"-1";return 0;
}

  技巧:通过矩阵的初等变换,通过尝试解来推测出每个未知数,复杂度O(n^3)

 

6.点的变换

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 39+7,mod = 1e3;
int n,m,T;
struct matrix{ll mat[N][N];}a[N];
matrix operator *(const matrix &a,const matrix &b){matrix c;memset(c.mat,0,sizeof(c.mat));for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){for(int k=1;k<=n;k++){c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;}}}return c;
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){int x,y;cin>>x>>y;a[i].mat[1][1]=x;a[i].mat[1][2]=x;}for(int i=1;i<=m;i++){int op,p,q,x;cin>>op>>x;if(op==1){cin>>p>>q;matrix k;memset(k.mat,0,sizeof(k.mat));k.mat[1][1]=k.mat[2][2]=k.mat[3][3]=1;k.mat[1][3]=p;k.mat[2][3]=q;matrix ans=k*a[x];cout<<ans.mat[1][1]<<' '<<ans.mat[1][2]<<'\n'; }else if(op==2){cin>>p;matrix k;memset(k.mat,0,sizeof(k.mat));k.mat[1][1]=k.mat[2][2]=p;k.mat[3][3]=1;matrix ans=k*a[x];cout<<ans.mat[1][1]<<' '<<ans.mat[1][2]<<'\n'; }else if(op==3){matrix k;memset(k.mat,0,sizeof(k.mat));k.mat[2][2]=-1;k.mat[1][1]=k.mat[3][3]=1;matrix ans=k*a[x];cout<<ans.mat[1][1]<<' '<<ans.mat[1][2]<<'\n'; }else if(op==4){matrix k;memset(k.mat,0,sizeof(k.mat));k.mat[1][1]=-1;k.mat[2][2]=k.mat[3][3]=1;matrix ans=k*a[x];cout<<ans.mat[1][1]<<' '<<ans.mat[1][2]<<'\n'; }}return 0;
}

  技巧:通过矩阵乘法,巧妙地将点的一些操作变化为矩阵的运算

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/789405.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第2天---RSA基础题型

T1.知pqe求d解m题目: from Crypto.Util.number import *flag = bNSSCTF{******}p = getPrime(512) q = getPrime(512) n = p*q e = 65537 phi = (p-1)*(q-1)m = bytes_to_long(flag)c = pow(m, e, n)print(fp = {p}) print(fq = {q}) print(fe = {e}) print(fc = {c}) p = 105…

带记忆的对话api上线

Link.AI 记忆对话 API原生支持开发者在应用/工作流中设置的记忆功能。开发者无需自行维护上下文记忆并通过messages参数传递,只需传入用户问题和身份标识即可,由系统按用户维度对上下文记忆进行维护,从而实现长期记忆下的多轮对话。API 简介 Link.AI 已为开发者提供了调用智…

devexpress 组件使用研究

1.提示框private void textEdit1_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == ( char)Keys.Enter) { AlertControl alert = new AlertControl(); alert.Show(this, "提示", textEdit1.Text, true);} }

Vue2实现应用添加水印的功能

需求 有的情况,我们需要给我们的网页添加水印。我们可以使用第三方库Watermark Design。官方地址:https://watermark-design.github.io/watermark/zh/ 效果示例代码 入口文件main.js import WatermarkDesign from @watermark-design/vue; Vue.use(WatermarkDesign)vue容器App…

Hive源码解析

1.概述 Apache Hive是一款建立在Hadoop之上的数据仓库工具,它提供了类似于SQL的查询语言,使得用户能够通过简单的SQL语句来处理和分析大规模的数据。本文将深入分析Apache Hive的源代码,探讨其关键组件和工作原理,以便更好地理解其在大数据处理中的角色。 2.内容 在开始源代…

芒格-“用幸存者心态去对待问题,永远不要有受害者心态”

我不会因为人性而感到意外,也不会花太多时间感受背叛, 我总是低下头去调整自己,去适应这一类事情, 所以我不允许自己花太多时间,去感受背叛, 但凡有一丁点这种想法,从我脑海闪过,我就马上规避掉了, 我不喜欢任何成为受害者的感觉, 我认为这是一种反其道而行之的人类思…

三分钟总结开源流程表单的优势特点

今天一起来看看开源流程表单的优势特点,一起了解它为何能助力企业降本增效。实现流程化办公,可以借助低代码技术平台、开源流程表单的优势特点。作为当前较为理想的平台产品,低代码技术平台凭借够灵活、好操作、可视化界面的优势特点,得到了通信业、医疗、高校等很多行业客…

使用zig语言制作简单博客网站(六)文章详情页

前端代码前端代码 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" …

为何选择合适的文档管理系统至关重要?

国内外主流的 10 款文档管理系统对比:1.PingCode;2.Worktile;3.飞书文档;4.石墨文档;5.语雀;6.Google Docs;7.Dropbox Business;8.Confluence;9.Microsoft OneDrive;10.Box。在当今快速发展的商业环境中,众多企业面临的一个主要挑战是如何有效管理日益增长的文件和数…