首页 > 其他分享 >【数论】1 矩阵快速幂(斐波那契)

【数论】1 矩阵快速幂(斐波那契)

时间:2024-07-25 12:55:37浏览次数:15  
标签:运算 快速 矩阵 long 斐波 那契 递推 乘法

Tips:本篇blog适合刚开始学习数论部分的同学

本题解仅代表个人思路,如有异议欢迎批评指正,谢谢

一. 概述

该章节讲述的是矩阵运算及快速幂的概念,学过的同学可以跳过本章,直接看矩阵快速幂

1.矩阵

矩阵类似于向量,我们可以这么来表示一个矩阵

\begin{pmatrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9 \end{pmatrix}

如上图,表示了一个 3*3 的矩阵。

矩阵也有加减乘法运算(请注意矩阵没有除法运算),并且这些运算都是矩阵之间的,即可以矩阵加矩阵但不能矩阵加数字

2.矩阵加减

矩阵的加减运算时,只有两个同型矩阵(即行列数相同)才能进行加减运算,两个矩阵相同位置上的数做加减运算,最终会得到一个矩阵,就是运算结果,例如

\begin{pmatrix} 4 & 6 & 3\\ 2 & 1 & 5 \end{pmatrix} + \begin{pmatrix} 3 & 6 & 1\\ 5 & 4 & 2 \end{pmatrix} = \begin{pmatrix} 7 & 12 & 4\\ 7 & 5 & 7 \end{pmatrix}  

可以看出,矩阵的加减法是具有交换律和结合律的。 

3.矩阵乘法 

矩阵乘法与加减法略有不同,矩阵进行乘法运算时,不一定两个矩阵是同型的(即不一定行列数相同),矩阵乘法的计算方法为

设 A * B = C (A,B,C均为矩阵),那么有

 C(i,j) = \sum A(i,k)*B(k,j)

我们举个形象的例子

\begin{pmatrix} 1 & 3\\ 2 & 2 \end{pmatrix} * \begin{pmatrix} 3 & 1\\ 4 & 2 \end{pmatrix} = \begin{pmatrix} 1*3+3*4 & 1*1+3*2\\ 2*3+2*4 & 2*1+2*2 \end{pmatrix} = \begin{pmatrix} 15 & 7\\ 14 & 7 \end{pmatrix}

到这里应该很清楚了,所以可以看出,矩阵乘法满足结合律,但不满足交换律 

4.快速幂 

快速幂可以加速幂运算,试想一下,如果我们直接枚举来进行幂运算,时间复杂度是 O(n) 。

我们可以用快速幂来优化这一过程,我们用类似二进制分解的原理,利用位运算来加速,最终的时间复杂度可以达到 O(log n) 。

具体的代码实现是这样滴

long long qpow(long long x,long long y)
{
	long long ans = 1;
	while (y)
	{
		if (y & 1) ans = (ans * x) % mod;//mod是模数
		x = (x * x) % mod;
		y >>= 1;
	}
	return ans;
}

二. 矩阵快速幂

1.引入

很多递推的题目,需要我们来递推求解状态,这时候的复杂度一般是 O(n) 的,但当 n 达到 10^{18} 的量级时,就可以采用矩阵快速幂来进行加速

例如下面这道题目

斐波那契数列 - 洛谷icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1962

2.思路

这一题中,n 达到 10^{18} 的量级,所以很显然不能再用普通的递推来求解了,我们可以使用矩阵快速幂。

如何进行求解呢?

我们知道,设斐波那契数列为 f ,那么其递推公式为:

f_1 = f_2 = 1        f_i = f_i-1 + f_i-2 (i\geq 3)

我们尝试把这个递推式放到矩阵里,就变成了这个样子:

[f_i,f_{i-1}] = [f_{i-1},f_{i-2}] * \begin{bmatrix} 1 & 1\\ 1 & 0 \end{bmatrix}

大家不妨代入一下试一试。

所以这个式子里,最后一个矩阵是如何推出来的呢?

我们可以用列表法来推出最后一个矩阵,我们以后计算的就是这个矩阵的幂。

矩阵f_{i-1}f_{i-2}
f_{i}11
f_{i-1}10

可以发现,我们只要让表中每一行值为1所对应的值加在一起等于这一行代表的值即可。

接下来,我们考虑如何用矩阵快速幂来求解。

可以发现,把上面的矩阵乘法求斐波那契数列的式子不断展开,就会变成这个样子:

[f_i,f_{i-1}] = [f_{1},f_{2}] * \begin{bmatrix} 1 & 1\\ 1 & 0 \end{bmatrix}^{n-2}

其中矩阵的幂次取决于你是从哪一个值开始递推,如果从 f_0 = 0,f_1 = 1 开始递推也是可以的,但是要改成:

[f_i,f_{i-1}] = [f_{0},f_{1}] * \begin{bmatrix} 1 & 1\\ 1 & 0 \end{bmatrix}^{n-1}

所以,我们用求解快速幂的方法带入到矩阵中,再模拟矩阵乘法,就可以用 O(logn) 的复杂度求解了。

3. 代码实现

要注意的是,矩阵 ans 初始化的时候应该类似于数字中的 1 ,所以我们把矩阵 ans 从左上到右下的所有值都初始化为1,其他初始化为0,这样就是一个初始矩阵了。

大家可以尝试一下,很容易发现这个道理。

#include <bits/stdc++.h>
using namespace std;
long long n;
const int mod = 1e9+7; //模数
struct A //结构体存矩阵
{
	long long a[3][3];
};
A multi(A a,A b) //模拟矩阵乘法
{
	A ans;
	for (int i=1;i<=2;i++)
	{
		for (int j=1;j<=2;j++)
		{
			ans.a[i][j] = 0;
			for (int k=1;k<=2;k++)
			{
				ans.a[i][j] = (ans.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
				ans.a[i][j] %= mod;
			}
		}
	}
	return ans;
}
long long qpows(long long b)
{
	A ans,a;
	a.a[1][1] = 1; //初始化斐波那契
	a.a[1][2] = 1;
	a.a[2][1] = 1;
	a.a[2][2] = 0;
	ans.a[1][1] = 1; //初始化答案矩阵
	ans.a[1][2] = 0;
	ans.a[2][1] = 0;
	ans.a[2][2] = 1;
	while (b) //快速幂
	{
		if (b & 1) ans = multi(ans,a);
		a = multi(a,a);
		b >>= 1;
	}
	return ans.a[1][1]%mod;
	
}
int main()
{
	cin >> n;
	if (n <= 2)  //特判
	{
		cout<<1;
		return 0;
	}
	cout<<qpows(n-1);
	return 0;
}

三. 结语

 矩阵快速幂的应用范围相当广泛,当我们需要优化递推或动态规划时,往往会考虑使用矩阵快速幂,大家可以再去练习一下 广义斐波那契数列 - 洛谷 来巩固所学内容。

标签:运算,快速,矩阵,long,斐波,那契,递推,乘法
From: https://blog.csdn.net/weixin_52163022/article/details/140683700

相关文章

  • 抖音短视频seo矩阵系统源码开发搭建私有化部署流程分享-----PHP+SaaS独立部署
      抖音seo源码优化逻辑抖音SEO是通过一系列的技术手段和优化策略来提升视频内容在抖音平台内的曝光率和排名。其中主要包括以下几个方面:1.关键词优化。通过对视频的标题、描述等元素的关键词进行优化,提高相关性和匹配度,让用户更容易搜索到相关视频。2.标签优化。在上传视......
  • 矩阵系统代码的核心思维
       随着信息技术的飞速发展,矩阵系统软件作为一种强大的工具,已经在多个领域中展现出其独特的价值。矩阵系统软件的核心原理基于数学中的矩阵理论,通过构建复杂的矩阵运算模型,实现对数据的高效处理和分析。本文将对矩阵系统软件进行深入解析,包括其原理、应用、优势以及未来趋......
  • 【笔记】矩阵的行列式
    定义行列式(Determinant)是对\(n\)阶方阵\(A\)定义的,是一个标量。\(A\)的\(n\)阶行列式\(\operatorname{det}(A)\)或\(|A|\)定义如下:\[\operatorname{det}(A)=\sum_p(-1)^{\operatorname{sgn}(p)}\prod_{i}A[i][p_i]\]这里将排列的奇偶性定义为了\(\operatorname{sgn......
  • 错误“对于非平面校准装置,必须在函数‘cvCalibrateCamera2Internal’中指定初始固有矩
    我遇到的错误的完整跟踪:在stereo_calibrate中ret,cameraMatrix1,distCoeffs1,cameraMatrix2,distCoeffs2,R,T,E,F,perViewErrors,_,_=cv2.stereoCalibrateExtended(cv2.error:OpenCV(4.10.0)/io/opencv/modules/calib3d/src/calibration.cpp:1682:error:(-5:Badargument)......
  • 应用数学与机器学习基础 - 数值计算之梯度之上Jacobian和Hessian矩阵篇
    序言在数值计算与优化理论的广阔天地里,梯度作为一阶导数的向量表示,是理解函数局部变化率及进行最优化求解的基础工具。然而,当问题的复杂度提升,单一梯度信息往往不足以全面刻画函数的多变量间相互作用及更高阶的变化特性。此时,Jaco......
  • 代码随想录 day33 斐波那契数 | 爬楼梯 |使用最小花费爬楼梯
    斐波那契数斐波那契数解题思路利用代码随想录给出的解题模板进行解题。先确定dp数组和dp下标的含义,之后需要确定遍历的顺序,接着我们通过枚举获得遍历的规矩,最后确定dq的初始值。知识点动态规划心得第一次做动态规划,主要是掌握基本的解题思路,了解一下到底是怎么解决问题的......
  • 41-50题矩阵和字符串 在Java中,将大写字符转换为小写字符的方法主要有以下几种:
    20240723一、数组最后几个和字符串的两个448.找到所有数组中消失的数字(和645.错误的集合差不多)283.移动零118.杨辉三角119.杨辉三角II661.图片平滑器(没看懂)598.区间加法II566.重塑矩阵303.区域和检索-数组不可变520.检测大写字母125.验证回文串二、在Jav......
  • 函数传参,递归函数(汉诺塔,裴波那契数列),预处理
    递归函数 获得斐波那契数列的第n项的值斐波那契数列是指这样一个数列:1,1,2,3,5,8,13,21,34,55,89……这个数列从第3项开始,每一项都等于前两项之和。#include<stdio.h>intFbnq(intn){if(n==1){return1;}elseif(n==2){return1......
  • 稀疏迭代求解器无矩阵方法预处理器
    如何为无矩阵左侧的稀疏迭代方法(TFQMR、GMRES、CGS等)定义预处理器(SPILU、SPAI等)?我使用无矩阵A(使用LinearOperator和matvec)定义了Ax=b。因此,我没有创建矩阵A并将其保存在内存中。例如,在这种情况下,我如何构建SPILU预处理器?我在所有教程和示例中看到预处理器是使用矩阵L......
  • 【独立开发者】小程序及H5框架推荐,快速构建你的产品矩阵
    在当今严峻的就业环境下,越来越多的程序员选择独立开发这个方向。希望靠个人力量,打造出属于自己的产品,通过运营产品盈利。一般来说独立开发有两种打法,一种是深度垂直,是指在某个方面或产品不断深入不断精进,给客户提供更专业产品更高质量的服务。另一种是横向覆盖,即通过涉足......