首页 > 其他分享 >矩阵优化学习笔记

矩阵优化学习笔记

时间:2023-07-10 21:56:33浏览次数:45  
标签:Mat 矩阵 笔记 times cdots bmatrix 优化 mat

前言

矩阵优化是一种比较靠思维的优化算法,一般简单题考的比较少。

个人认为矩阵优化中在运用,所以放了几道题目来讲解。

定义

矩阵

一个 \(m\times n\) 的矩阵是一个由 \(m\) 行 \(n\) 列元素排列成的矩形阵列。大概长成下面这个样子的。

\[A = \underbrace{\begin{bmatrix} a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\ a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m,1} & a_{m,2} & \cdots & a_{m,n} \end{bmatrix}}_{m}\Bigg\}n \]

也就是说,存储以一个矩阵只需要存储它的行、列以及每个元素的值即可。

若两个矩阵行数和列数都相同,则我们管这两个矩阵叫做同型矩阵。

矩阵的运算

加法&减法

两个同型矩阵的加法运算如下

矩阵与数

将矩阵每个位置加/减这个数即可。

矩阵与矩阵

\[\begin{bmatrix} a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\ a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m,1} & a_{m,2} & \cdots & a_{m,n} \end{bmatrix}+\begin{bmatrix} b_{1,1} & b_{1,2} & \cdots & b_{1,n} \\ b_{2,1} & b_{2,2} & \cdots & b_{2,n} \\ \vdots & \vdots & \ddots & \vdots \\ b_{m,1} & b_{m,2} & \cdots & b_{m,n} \end{bmatrix}=\begin{bmatrix} a_{1,1}+b_{1,1} & a_{1,2}+b_{1,2} & \cdots & a_{1,n}+b_{1,n} \\ a_{2,1}+b_{2,1} & a_{2,2}+b_{2,2} & \cdots & a_{2,n}+b_{2,n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m,1}+b_{m,1} & a_{m,2}+b_{m,2} & \cdots & a_{m,n}+b_{m,n} \end{bmatrix} \]

上述矩阵为加法运算,减法同理。一般我们不考虑非同型矩阵的加减法运算。

乘法

矩阵与数

将矩阵每个元素都乘上那个数即可。

矩阵与矩阵

两个矩阵可以相乘必须要满足前一个矩阵的列数等于后一个矩阵的行数。

或者说,\(A\) 矩阵的大小为 \(n\times m\),\(B\) 矩阵的大小为 \(m\times l\),才能进行 \(A\times B\) 这个运算。

若 \(C=A\times B\),则(此处矩阵大小同上文)

\[C_{i,j}=\sum_{k=1}^{m}{A_{i,k}\times B_{k,j}} \]

不难发现,\(C\) 的大小为 \(n\times l\)。

矩阵乘法满足一下几条运算律:

\[(AB)C=A(BC)\\ A(B+C)=AB+BC\\ (B+C)A=BA+CA \]

但请注意,矩阵乘法不满足交换律,即 \(AB\neq BA\)。

单位矩阵

在数的运算中,有 \(1\times a=a\)。在矩阵运算中,也有一个矩阵满足任意矩阵乘该矩阵等于原矩阵。若原矩阵为 \(n\times m\) 大小的矩阵 \(A\),这个矩阵为 \(m\times m\) 大小的矩阵 \(B\),则

\[B=\begin{bmatrix} 1 & \cdots & 0 \\ 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & 1 \end{bmatrix} \]

其左上到右下的对角线上的数都为 \(1\),其余都为 \(0\)。我们管这样的矩阵叫单位矩阵。一个矩阵乘单位矩阵后完全不变。

运用

P3390 【模板】矩阵快速幂

将矩阵定义为结构体并重载运算符,直接计算即可。

#include<iostream>
#include<cstring>
using namespace std;
long long b,n,k,l=100,mod=1000000007;
struct Mat
{
	#define N 110
	long long mat[N][N];
};
Mat operator* (Mat a,Mat b)
{
	Mat c;
	memset(c.mat,0,sizeof(c.mat));
	for(int k=1;k<=l;k++)
	for(int i=1;i<=l;i++)
	{
		if(a.mat[i][k]<=0)
		 continue;
		for(int j=1;j<=l;j++)
		{
			if(b.mat[k][j]<=0)
			 continue;
			c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
		}
	}
	return c;
}
Mat operator^ (Mat a,long long k)
{
	Mat c;
//	for(int i=1;i<=l;i++)
//	for(int j=1;j<=l;j++)
//	 c.mat[i][j]=(i==j);
	memset(c.mat,0,sizeof(c.mat));
	for(int i=1;i<=n;i++)
	 c.mat[i][i]=1;
	while(k)
	{
		if(k&1)
		 c=a*c;
		a=a*a;
		k>>=1;
	}
	return c;
}
int main()
{
	cin>>n>>k;
	Mat x;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	 cin>>x.mat[i][j];
	x=x^k;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		 cout<<x.mat[i][j]<<" "; 
		cout<<endl;
	}
	
}

P1939 【模板】矩阵加速(数列)

注意到 \(n\leq 2\times 10^9\),不能直接用递推做。用矩阵快速幂快速计算。

简单的用矩阵优化的题都是把所有要用的东西都扔进一个矩阵里,比如这题:

\[W=\begin{bmatrix}f_i\\ f_{i-1}\\ f_{i-2}\end{bmatrix} \]

其中 \(f_i\) 表示求得的数列 \(a\) 第 \(i\) 项的值。但要注意,由于这个矩阵是由 \(i-1\) 的矩阵推过来的,所以矩阵内能引用到的数分别是 \(a_{i-1},a_{i-2},a_{i-3}\)。

在递推式里,推导答案的式子有 \(m\) 项,则这个矩阵的大小为 \(m\times m\)。

我们需要一个矩阵 \(B\) 使得

\[B\times \begin{bmatrix}f_{i-1}\\ f_{i-2}\\ f_{i-3}\end{bmatrix}=\begin{bmatrix}f_i\\ f_{i-1}\\ f_{i-2}\end{bmatrix} \]

在这题里,这个矩阵 \(B\) 长成下面这样:

\[\begin{bmatrix}a_{1,1} & a_{1,2} & a_{1,3}\\ a_{2,1} & a_{2,2} & a_{2,3}\\ a_{3,1} & a_{3,2} & a_{3,3} \end{bmatrix} \]

也就是说,这个矩阵与上述矩阵相乘的意义为

\[f_i=a_{1,1}f_{i-1}+a_{1,2}f_{i-2}+a_{1,3}f_{i-3}\\ f_{i-1}=a_{2,1}f_{i-1}+a_{2,2}f_{i-2}+a_{2,3}f_{i-3}\\ f_{i-2}=a_{3,1}f_{i-1}+a_{3,2}f_{i-2}+a_{3,3}f_{i-3}\\ \]

我们可以比较容易的推出这个矩阵为

\[\begin{bmatrix}1 & 0 & 1\\ 1 & 0 & 0\\ 0 & 1 & 0 \end{bmatrix} \]

如果要用矩阵的出 \(f_i\),那么大概是这样的

\[\begin{bmatrix}f_3=1\\ f_2=1 \\ f_{1}=1\end{bmatrix}\times\underbrace{\begin{bmatrix}1 & 0 & 1\\ 1 & 0 & 0\\ 0 & 1 & 0 \end{bmatrix} \times \cdots \times \begin{bmatrix}1 & 0 & 1\\ 1 & 0 & 0\\ 0 & 1 & 0 \end{bmatrix} }_{i-3\text{个}} \]

然后就可以直接用矩阵快速幂来做了。一共有 \(i-3\) 个矩阵 \(B\) 是因为 \(x\in\{1,2,3\}\) 的值为 \(1\),注意答案为所得矩阵的第一项。

#include<iostream>
#include<cstring>
using namespace std;
#define int long long
#define mod 1000000007
struct Mat
{
	#define N 4
	int mat[N][N];
};
int t,n,l=3;
Mat operator* (Mat a,Mat b)
{
	Mat c;
	memset(c.mat,0,sizeof(c.mat));
	for(int k=1;k<=3;k++)
	for(int i=1;i<=3;i++)
	for(int j=1;j<=3;j++)
	{
		if(a.mat[i][k]<0||b.mat[k][j]<0)
		 continue;
		c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
	}
	return c;
}
Mat operator^ (Mat a,int k)
{
	Mat c;
	memset(c.mat,0,sizeof(c.mat));
	for(int i=1;i<=3;i++)
	 c.mat[i][i]=1;
	while(k)
	{
		if(k&1)
		 c=a*c;
		a=a*a;
		k>>=1;
	}
	return c;
}
signed main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		if(n<=3)
		{
			cout<<1<<endl;
			continue;
		}
		Mat a,x;
		memset(a.mat,0,sizeof(a.mat));
		memset(x.mat,0,sizeof(x.mat));
		a.mat[1][1]=a.mat[1][3]=a.mat[2][1]=a.mat[3][2]=1;
		x.mat[1][1]=x.mat[1][2]=x.mat[1][3]=1;
		x=x*(a^(n-3));
		cout<<x.mat[1][1]<<endl;
	}
}

P1962 斐波那契数列

思路和上题差不多,都是找到一个转移矩阵。

甚至比上题还要简单一些。

#include<iostream>
#include<cstring>
using namespace std;
unsigned long long b,n,k,l=2,p=1000000007;
struct Mat
{
	unsigned  long long mat[3][3];
};
Mat operator* (Mat a,Mat b)
{
	Mat c;
	memset(c.mat,0,sizeof(c.mat));
	for(long long k=1;k<=l;k++)
	for(long long i=1;i<=l;i++)
	{
		if(a.mat[i][k]<=0)
		 continue;
		for(long long j=1;j<=l;j++)
		{
			if(b.mat[k][j]<=0)
			 continue;
			c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%p;
		}
	}
	return c;
}
Mat operator^ (Mat a,long long k)
{
	Mat c;
//	for(int i=1;i<=l;i++)
//	for(int j=1;j<=l;j++)
//	 c.mat[i][j]=(i==j);
	memset(c.mat,0,sizeof(c.mat));
	for(long long i=1;i<=2;i++)
	 c.mat[i][i]=1;
	while(k)
	{
//		cout<<">>"<<k<<endl;
		if(k&1)
		 c=a*c;
		a=a*a;
		k>>=1;
	}
	return c;
}
int main()
{
	cin>>n;
	Mat x,y;
	memset(x.mat,0,sizeof(x.mat));
	memset(y.mat,0,sizeof(y.mat));
	x.mat[1][1]=1;
	x.mat[2][1]=1;
	y.mat[1][1]=y.mat[1][2]=1;
	y.mat[2][1]=1;
	y=y^(n-1);
	x=x*y;
	cout<<x.mat[1][1]<<endl;
}

P5789 [TJOI2017] 可乐(数据加强版)

标签:Mat,矩阵,笔记,times,cdots,bmatrix,优化,mat
From: https://www.cnblogs.com/lyz09-blog/p/study-matrix-optimize.html

相关文章

  • 【Python】Locust持续优化:InfluxDB与Grafana实现数据持久化与可视化分析
    前言在进行性能测试时,我们需要对测试结果进行监控和分析,以便于及时发现问题并进行优化。Locust在内存中维护了一个时间序列数据结构,用于存储每个事件的统计信息。这个数据结构允许我们在Charts标签页中查看不同时间点的性能指标,但是正因为LocustWebUI上展示的数据实际上是存储......
  • 「学习笔记」KMP 算法
    前置知识前缀是指从串首开始到某个位置\(i\)结束的一个特殊子串.真前缀指除了\(S\)本身的\(S\)的前缀.举例来说,字符串abcabeda的所有前缀为{a,ab,abc,abca,abcab,abcabe,abcabed,abcabeda},而它的真前缀为{a,ab,abc,abca,abcab,abcabe,abcabed}.......
  • 隐马尔可夫学习笔记(一)
    隐马尔可夫模型学习笔记前言学习隐马尔可夫模型时,最大的困难便是一堆公式与实际问题对应不上号。原因可能还是在于对概率论的理解太表面,且隐马尔可夫模型考虑了时间因素,显然这样的随机过程一时半会是难以形象的理解的。因此,本文采用先举例,后定义公式的方式来学习隐马尔可夫模型。思......
  • 支持向量机学习笔记--实现篇(三)
    支持向量机学习笔记(三)前言两篇文章阐述了支持向量机的原理,在数学的海洋中遨游了快一周,实在撑不下去了,现在准备亲自来实现一把支持向量机的学习算法,序列最小最优化算法,依然需要数学知识和少量的编程基础。参考的书籍为李航的《统计学习方法》和PeterHarrington的《机器学习实战》,参......
  • 支持向量机学习笔记--原理篇(一)
    支持向量机学习笔记–原理篇(一)前言初步学习机器学习给我最大的感受是它背后需要强大的数学知识,理论推导往往能帮助我们理解其本质。而在我看来,单纯的求解数学问题还不够,我们需要有把这部分理论知识运用到实际应用中去的能力。支持向量机(supportvector)是机器学习中用来解决监督分......
  • 软件测试工程师笔记
    腾讯的面试官就贼喜欢问软件测试基础部分,字节的还好…所以在我以前通过校招上岸字节跳动后,将我自己找工作认真总结,并且写成面经文章了。这份笔记包括软件测试基础、Linux、Python、计算机网络、常见软件测试工具(LR、Jmeter)、数据库(MySQL为主)、常见逻辑题、以及软件测试面试中需要......
  • [TM4]TM4C123G使用笔记(一)
    [TM4]TM4C123G使用笔记(一)TI的板子真让人头大......
  • openGauss学习笔记-05 openGauss gsql连接与使用方法
    openGauss学习笔记-05openGaussgsql连接与使用方法openGauss提供了在命令行下运行的数据库连接工具gsql。此工具除了具备操作数据库的基本功能,还提供了若干高级特性,便于用户使用。本节主要介绍如何使用gsql本地连接数据库。您需要提供数据库的名称以及数据库主节点的端口号。5.......
  • 线性规划对偶 & 全幺模矩阵
    一、线性规划的一般形式线性规划问题,有\(n\)个变量\(x_1,x_2,\cdots,x_n\),满足一些线性约束的条件下,求目标函数的最值。二、线性规划的标准形式设有\(n\)个变量,\(m\)个线性约束,目标函数为\(z\)。\[\maxz=\sum_{i=1}^nc_ix_i\]\[\text{s.t.}\begin{cases}......
  • 网络流学习笔记
    网络流基本概念(fromOIwiki)网络:有向图\(G=(V,E)\),其中每条边有一个流量\(c\),当\((u,v)\notinE\)时,\(c_{(u,v)}=0\)。其中有两个特殊的点:源点\(s\inV\),\(t\inV\)。流:定义函数\(f(u,v)\),满足下列条件:容量限制:\(f(u,v)\lec(u,v)\)。斜对称性:\(f(u,v)......