「数学::快速幂」矩阵快速幂运算|快速斐波那契数列 / LeetCode 509(C++)

目录

概述

思路

算法过程

复杂度

Code


概述

LeeCode 509:

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n) 。

我们介绍过快速幂运算:「数学::快速幂」基本快速幂运算|快速幂取模运算(C++)
快速幂不仅可以用于求数的幂,也可以求矩阵的幂,进而进行将一些递推算法优化成logn算法。


思路

我们首先要求你掌握一些线性代数知识:矩阵的乘法。

矩阵(Matrix)是一个按照方阵排列的复数或实数集合。

矩阵乘法: {

A(mn)*B(st)=C(mt),一个m行n列的矩阵A乘以一个s行t列的矩阵B等于一个m行t列的矩阵的C。

其中,我们要求n必须等于s,否则无法相乘。

接下来我们称矩阵的i行j列为[i][j]。

\sumA[i][k]*B[k][j]=C[i][j]  (\sum:枚举k从1到n)

即:C[i][j]的元素等于A的i行每个元素与B的j行每个对应元素的积的累加和:

      ┌ 2 1 ┐ * ┌ 1 0 ┐ = ┌ 3 3 ┐└ 0 1 ┘   └ 1 3 ┘   └ 1 3 ┘

A矩阵的行数与B矩阵的列数是可以不相等的:

                ┌ 1 1 ┐ [ 1 1 ] * └ 1 0 ┘ = [ 2 1 ]

此外矩阵乘法具有结合律:A*B*.....*B=A*(B)ⁿ。

}

因此考虑:F(n) = F(n - 1) + F(n - 2),我们可以将其递推式写为矩阵乘法:

                      ┌ 1 1 ┐ [ Fn-1 Fn-2 ] * └ 1 0 ┘ = [ Fn Fn-1 ]

也就是说,将初始的\begin{bmatrix} F1 &F0 \end{bmatrix}乘以有系数矩阵\begin{bmatrix} 1& 1\\ 1& 0 \end{bmatrix},就可以递推得到\begin{bmatrix} F2 &F1 \end{bmatrix}

由于矩阵乘法具有结合律:A*B*.....*B=A*(B)ⁿ,我们可以先计算pow(\begin{bmatrix} 1& 1\\ 1& 0 \end{bmatrix},n-1),在执行\begin{bmatrix} F1 &F0 \end{bmatrix}*pow(\begin{bmatrix} 1& 1\\ 1& 0 \end{bmatrix},n-1),就可以得到\begin{bmatrix} Fn &Fn-1 \end{bmatrix}


算法过程

pow函数可以使用quick_pow快速实现。

我们还需要重载*运算符来实现矩阵乘法。

使用三重for循环枚举A的i行,B的j列以及A[i][k]*B[k][j] 。

using row = vector<long long>;
using matrix = vector<row>;
matrix operator *(const matrix& A, const matrix& B) {matrix ans(A.size(), row(B[0].size()));for (int i = 0; i < A.size(); i++)for (int j = 0; j < B[0].size(); j++)for (int k = 0; k < A[0].size(); k++)ans[i][j] = (ans[i][j] + A[i][k] * B[k][j]);return ans;
}

正如普通的quick_pow初始化ans为1,我们将矩阵快速幂的ans初始化为\begin{bmatrix} 1&0 \\ 0&1 \end{bmatrix} ,即单位矩阵,它的定位等同于1,任何矩阵乘以单位矩阵都等于原矩阵。

matrix quick_pow(matrix x, int n) {matrix ans={{1,0},{0,1}};while (n) {if (n & 1)ans = ans * x;x = x * x;n >>= 1;}return ans;
}

复杂度

时间复杂度: O(logn)

空间复杂度: O(1)


Code

long long quick_pow(long long x, int n) {long long ans = 1;while (n) {if (n & 1)ans *= x;x *= x;n >>= 1;}return ans;
}
using row = vector<long long>;
using matrix = vector<row>;
matrix operator *(const matrix& A, const matrix& B) {matrix ans(A.size(), row(B[0].size()));for (int i = 0; i < A.size(); i++)for (int j = 0; j < B[0].size(); j++)for (int k = 0; k < A[0].size(); k++)ans[i][j] = (ans[i][j] + A[i][k] * B[k][j]);return ans;
}
matrix quick_pow(matrix x, int n) {matrix ans={{1,0},{0,1}};while (n) {if (n & 1)ans = ans * x;x = x * x;n >>= 1;}return ans;
}
class Solution {
public:int fib(int n) {if (!n)return 0;matrix m = { {1,0} }, coefficient = { {1,1},{1,0} };matrix c = quick_pow(coefficient, n - 1);matrix ans = m * c;return ans[0][0];}
};

 

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

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

相关文章

linux--库指令

ldd ldd 可执行文件路径 显示依赖的库的查找路径以及是否查找到了。

Request2:Post请求和Json

百度翻译拿到自己想看的数据&#xff0c;下图查看请求到数据的请求 preview提前看下 取出对应的RequestUrl &#xff0c;看出来要使用的话得用post请求 #!/usr/bin/env python # -*- coding:utf-8 -*- import requests import json if __name__ "__main__":#1.指定…

SAP物料凭证报表字段调整

业务场景&#xff1a; 报表MB51的输入和输出字段调整&#xff1a; 输入&#xff08;选择界面&#xff09; 输出界面 可以看到在这是没有布局调整的 后台路径&#xff1a; SPRO-物料管理-库存管理和实际库存-报表-定义物料凭证列表的字段选择 事务码&#xff1a;SM30-V_MMI…

FPGA学习(6)-基础语法参数化设计阻塞与非阻塞

目录 1.两种参数化不改变源文件&#xff0c;只改仿真文件的值 2.参数化设计实现模块的重用 2.1不用参数化方法 2.1.1源文件 2.1.2仿真文件 2.1.3仿真波形及实验 2.2 用参数方法 2.2.1调用之前写的led灯闪烁模块&#xff0c;在本源函数中&#xff0c;例化4次调用之前的模…

史上最烂 spring transaction 原理分析

史上最烂 spring transaction 原理分析 事务定义、事务作用、事务特性、生命周期、数据库事务三种运行模式、数据库事务控制、并发事务问题、隔离级别、数据库事务实现原理、spring 事务传播行为、spring 事务核心组件、spring boot 事务相关组件、事务嵌套原理、编程式事务与声…

51单片机的万年历【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块时钟模块按键蜂鸣器等模块构成。适用于电子万年历、数字时钟万年历等相似项目。 可实现功能: 1、LCD1602实时显示年月日星期和北京时间&#xff0c;具备闰年判断功能 2、按键可设置闹钟时间 3、按键可修改当前时…

[Halcon矩阵] 通过手眼标定矩阵计算相机旋转角度

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…

06.队列介绍+实现

目录 一、队列的概念 二、队列的实现 1、头文件定义 2、功能函数实现 3、主函数测试 一、队列的概念 队列就像吃饭排队类似&#xff0c;先来先吃&#xff0c;先进先出。 队头&#xff1a;队列的头部。 队尾&#xff1a;队列的尾部。 入队&#xff1a;在队尾操作。 出队&…

STM32—BKP备份寄存器RTC实时时钟

1.BKP简介 BKP(Backup Registers)备份寄存器BKP可用于存储用户应用程序数据。当VDD&#xff08;2.0~3.6V&#xff09;电源被切断&#xff0c;他们仍然由VBAT(1.8~3.6V)维持供电。当系统在待机模式下被唤醒&#xff0c;或系统复位或电源复位时&#xff0c;他们也不会被复位TAMP…

【GAMES101笔记速查——Lecture 16 Ray Tracing4】

上节课的内容&#xff1a;辐射度量学、光线传播、反射方程、渲染方程、全局光照、概率论复习 这节课要介绍一种真实的渲染方法-蒙特卡洛路径追踪 目录 1 简单回顾 1.1 渲染方程&#xff08;The Rendering Equation&#xff09; 1.2 概率 2 蒙特卡洛积分&#xff08;Monte…

SQL Injection | SQL 注入概述

关注这个漏洞的其他相关笔记&#xff1a;SQL 注入漏洞 - 学习手册-CSDN博客 0x01&#xff1a;SQL 注入漏洞介绍 SQL 注入就是指 Web 应用程序对用户输入数据的合法性没有判断&#xff0c;前端传入后端的参数是可控的&#xff0c;并且参数会带入到数据库中执行&#xff0c;导致…

(10) GTest c++单元测试(mac版)

文章目录 概要安装实现机制-断言&#xff08;简单、独立的测试&#xff09;实现机制-测试套件实现机制-Test Fixture和事件 概要 官方文档 https://google.github.io/googletest/ 安装 git clone https://github.com/google/googletestcd googletestmkdir build && c…

数字化营销助企业在生态平台实现内卷突围

在当今数字化时代&#xff0c;企业竞争激烈&#xff0c;内卷化严重。而数字化生态平台建设与数字化营销为企业带来了新机遇。 数字化生态平台意义重大。它能整合企业内外资源&#xff0c;提高运营效率。打破地域限制&#xff0c;拓展市场&#xff0c;吸引更多客户。还能为企业创…

【AI副业项目】太离谱了!爆涨粉47W+,下一个风口项目AI+大健康养S赛道,单月变现30W,教你如何用AI做爆款健康养生账号

我一直说小红薯平台是最适合新手素人做的平台&#xff0c;去中心化的平台&#xff0c;任何普通人都可以在这个平台分一杯羹的平台。 但但但是很多朋友发小红薯作品都是超低的小眼睛&#xff0c;连最基本的流量都没拿到。 从他们的经历来看就是小红薯太难做了。那是没有掌握技…

【Vue】Vue3.0 (十二)、watchEffect 和watch的区别及使用

上篇文章&#xff1a; 【Vue】Vue3.0 &#xff08;十二&#xff09;、watch对ref定义的基本类型、对象类型&#xff1b;reactive定义的对象类型的监视使用 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Vue专栏&#xff1a;点击&#xff01; ⏰️创作时间&…

智慧油田智能安全管控方案-AI助力油气田安全管控升级

在科技日新月异的今天&#xff0c;万物纵横科技凭借其前沿的智慧油田智能安全管控方案&#xff0c;正引领着油气田行业向智能化、高效化转型。该方案深度融合了AI视频智能分析与AIoT&#xff08;物联网人工智能&#xff09;技术&#xff0c;为采油场、油气场的设备运维、环境监…

2024全网最详细CTF入门指南、CTF夺旗赛使用工具及刷题网站

2024年最新的CTF&#xff08;Capture The Flag&#xff0c;夺旗赛&#xff09;入门指南如下&#xff0c;涵盖了入门思路、常见题型及练习网站推荐&#xff0c;帮助你逐步了解并提升在CTF中的解题技巧。 如果你对网络安全入门感兴趣&#xff0c;我给大家整理好了相关资料&#…

Java集合剖析2】Java集合底层常用数据结构

一、数据结构与集合 接下来就要学习集合具体的实现类了&#xff0c;集合的实现类底层可能用1种或多种数据结构来存储数据。所以在学习集合的实现类前&#xff0c;我们有必要了解一下一些常见的数据结构&#xff0c;这样我们在后面查看集合实现类的底层源码时&#xff0c;才不会…

项目模块三:Socket模块

一、模块设计 1、套接字编程常用头文件展示 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <fcntl.h> 2、成员函数设计 &#xff08;1&#xf…

题目:连续子序列

解题思路&#xff1a; 首先&#xff0c;不能使用暴力枚举&#xff0c;时间为O(n2)&#xff0c;超时。以下为正确做法&#xff1a; 假设找到一段区间&#xff08;其和>m&#xff09;&#xff0c;如上图黄色部分&#xff0c;那么该区间加上i后面的元素形成的新区间和都>m&a…