矩阵及其应用

Basic

什么是矩阵

这真的是一个很复杂的问题…简单的说,矩阵是一个排列呈矩形的数集,比如说:

(13​24​)

矩阵的基本运算

在OI中,我们常用的是矩阵乘法,因此对于矩阵的加法、转置和数乘这里不做讲解。
对于一个 M×N 的矩阵 A 和一个 N×P 的矩阵 B,设矩阵 C 为 A 和 B 的乘积。
则 C 的第 i 行 第 j 列上的元素可表示为:

Ci,j​=k=1∑N​Ai,k​×Bk,j​

也就是说,C 矩阵中第 i 行第 j 列的数是由 A 矩阵第 i 行的数与 B 矩阵第 j 列的数分别相乘再相加得到的。

矩乘的性质

  • 矩乘只对形如 M×N 和 N×P 的两个矩阵有意义,且其结果一定是一个 M×P 的矩阵。
  • 矩乘满足结合律,读者可根据定义式自行证明。
  • 矩乘不满足交换律,根据定义式,这是显然的。

矩乘的代码实现


for(int i=1; i<=n; i++) {
    for(int j=1; j<=k; j++) {
	for(int h=1;h<=m;h++){
	    c[i][j]+=a[i][h]*b[h][j];

	}
    }
}

就这么简单。

单位矩阵

单位矩阵是满足除了第 i 行第 j 列的数是 1 外,其他的数都是 0 的矩阵。
根据矩乘定义式,极易发现单位矩阵乘任何矩阵都得所乘矩阵。

矩阵快速幂

由于矩乘满足结合律,因此我们可以用快速幂计算。
代码如下:

struct Martrix{
    int a[4][4];
    Martrix(){
    	memset(a,0,sizeof(a));
    }
    Martrix operator *(const Martrix B){
	Martrix res;
	for(int i=1;i<=3;i++){
	    for(int j=1;j<=3;j++){
		for(int k=1;k<=3;k++){
		    res.a[i][j]=(res.a[i][j]+a[i][k]*B.a[k][j])%mod;
		}
	    } 
	}
	return res;
    }
    void build(){
	for(int i=1;i<=3;i++){
	    a[i][i]=1;
	}
    }
};
Martrix qpow(Martrix A,int n){
    Martrix res;
    res.build();
    while(n){
	if(n&1){
	    res=res*A;
	}
	A=A*A;
	n>>=1;
    }
    return res;
}
	

没什么可说的。

矩阵的应用

矩阵优化递推

例:斐波那契数列

Fn​ 表示斐波那契数列中的第 n 项,给定 n≤1018,求 Fn​mod109+7 的值

考虑构造矩阵:

(Fn​​Fn+1​​)

注意到:

(Fn​​Fn+1​​)=(Fn−1​​Fn​​)(01​11​)

也就是说,我们可以维护矩阵 (F1​​F2​​) ,然后一直乘 (01​11​)即可。
代码:


const int mod=1e9+7;
struct Martrix{
	int a[3][3];
	Martrix(){
		a[1][1]=a[1][2]=a[2][1]=a[2][2]=0;
	}
	Martrix operator *(const Martrix& B){
		Martrix res;
		for(int i=1;i<=2;i++){
			for(int j=1;j<=2;j++){
				for(int k=1;k<=2;k++){
					res.a[i][j]=(res.a[i][j]+a[i][k]*B.a[k][j])%mod;
				}
			}
		}
		return res;
	}
	void build(){
		a[1][1]=a[2][2]=1;
	}
};
Martrix qpow(Martrix a,int n){
	Martrix res;
	res.build();
	while(n){
		if(n&1){
			res=res*a;
		}
		a=a*a;
		n>>=1;
	}
	return res;
}
void solve(){
	int n;
	cin>>n;
	if(n<=2){
		cout<<1<<endl;
		return;
	}
	Martrix F,A;
	F.a[1][1]=1,F.a[1][2]=1;
	A.a[1][1]=A.a[1][2]=A.a[2][1]=1;
	F=F*qpow(A,n-2);
	cout<<F.a[1][1]<<endl;
} //缩进挂了,懒得修了

其他内容正在施工中…

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值