【矩阵快速幂】封装类及测试用例及样例

news2024/11/18 13:44:05

作者推荐

视频算法专题

通俗的说,就是矩阵的乘方。

封装类

核心代码

class CMat
{
public:
	// 矩阵乘法
	static vector<vector<long long>> multiply(const vector<vector<long long>>& a, const vector<vector<long long>>& b) {
		const int r = a.size(), c = b.front().size(),iK = a.front().size();
		assert(iK == b.size());
		vector<vector<long long>> ret(r, vector<long long>(c));
		for (int i = 0; i < r; i++)
		{
			for (int j = 0; j < c ; j++) 
			{
				for (int k = 0; k < iK; k++)
				{
					ret[i][j] = (ret[i][j] + a[i][k] * b[k][j] ) % s_llMod;
				}
			}
		}
		return ret;
	}

	// 矩阵快速幂
	static vector<vector<long long>> pow( const vector<vector<long long>>& a, vector<vector<long long>> b, long long n) {
		vector<vector<long long>> res = a;
		for (; n; n /= 2) {
			if (n % 2) {
				res = multiply(res, b);
			}
			b = multiply(b, b);
		}
		return res;
	}
	static vector<vector<long long>> TotalRow(const vector<vector<long long>>& a)
	{
		vector<vector<long long>> b(a.front().size(), vector<long long>(1, 1));
		return multiply(a, b);
	}
protected:
	const static long long s_llMod = 1e9 + 7;
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{
	assert(t1 == t2);
}

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		Assert(v1[i], v2[i]);
	}
}


int main()
{
	vector<vector<long long>> pre = { {1,2} };
	vector<vector<long long>> mat = { {2,3},{1,10} };
	{	
		auto res = CMat::pow(pre, mat, 0);
		Assert(pre, res);
	}
	{
		auto res = CMat::multiply(pre, mat);
		Assert(vector<vector<long long>>{ {4, 23}}, res);
		auto res2 = CMat::pow(pre, mat,1);
		Assert(res2, res);
	}
	{
		auto res = CMat::pow(pre, mat, 2);
		auto res1 = CMat::multiply(pre, mat);
		auto res2 = CMat::multiply(res1, mat);
		Assert(res2, res);
		Assert(vector<vector<long long>>{ {31, 242}}, res);
	};

	for (int i = 3; i < 100; i++)
	{
		auto res = pre;
		for (int j = 0; j < i; j++)
		{
			res = CMat::multiply(res, mat);
		}
		auto res2 = CMat::pow(pre, mat, i);
		Assert(res2, res);
	}
	
}

具体例子

题目、分析和原理见:

【动态规划】【矩阵快速幂】【滚动向量】C++算法552. 学生出勤记录 II

原解法用二维表示状态,改成一维。 i是缺勤数量,j是连续迟到数,新的状态为:3*i+j
6种状态,故转移矩阵为6行6列,故结果矩阵为6列,6个数据1行就足够了。
令旧结果矩阵为mat1,转移矩阵为mat2,新矩阵为mat3,K mat1的列数,mat2的行数。则:
mat3[r][c] = Sum [ 0 , k ) i ^{i}_{[0,k)} [0,k)i(mat1[r][i]*mat2[i][c])

i在mat1中列号,在mat2中是行号。 也就是旧状态在第几列,mat2就在第几行。
新状态就是mat2的行号。

class Solution {
public:
	int checkRecord(int n) {
		vector<vector<long long>> pre(1, vector<long long>(6));//1行6列	
		pre[0][0] = 1;
		vector<vector<long long>> mat(6, vector<long long>(6));
		{	
			//之前的状态在pre是第几列,矩阵中就是第几行。新状态的列号就矩阵的列号
			//处理一次缺勤 ,缺勤两次排除
			for (int i = 0; i < 3; i++)
			{
				mat[i][3]++;
			}
			//处理请假
			for (int i = 0; i < 2; i++)
			{
				for (int j = 0; j < 2; j++)
				{
					const int pre = 3 * i + j;
					mat[pre][pre + 1]++;
				}
			}
			//处理正常
			for (int i = 0; i < 2; i++)
			{
				for (int j = 0; j < 3; j++)
				{
					const int pre = 3 * i + j;
					const int cur = 3 * i;
					mat[pre][cur]++;
				}
			}
		}
		auto res = CMat::pow(pre, mat, n);
		res = CMat::TotalRow(res);
		return res[0][0];
	}
};

测试用例

template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
Assert(v1[i], v2[i]);
}
}

int main()
{
int n;
{
Solution sln;
n = 0;
auto res = sln.checkRecord(n);
Assert(1, res);
}
{
Solution sln;
n = 1;
auto res = sln.checkRecord(n);
Assert(3, res);
}
{
Solution sln;
n = 2;
auto res = sln.checkRecord(n);
Assert(8, res);
}
{
Solution sln;
n = 3;
auto res = sln.checkRecord(n);
Assert(19, res);
}
{
Solution sln;
n = 4;
auto res = sln.checkRecord(n);
Assert(43, res);
}
{
Solution sln;
n = 5;
auto res = sln.checkRecord(n);
Assert(94, res);
}
{
Solution sln;
n = 6;
auto res = sln.checkRecord(n);
Assert(200, res);
}
{
Solution sln;
n = 7;
auto res = sln.checkRecord(n);
Assert(418, res);
}
{
Solution sln;
n = 10101;
auto res = sln.checkRecord(n);
Assert(183236316, res);
}
}

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 **C+

+17**
如无特殊说明,本算法用**C++**实现。

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

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

相关文章

八:分布式锁

1、为什么要使用分布式锁 锁是多线程代码中的概念&#xff0c;只有多任务访问同一个互斥的共享资源时才需要锁。单机应用开发时一般使用synchronized或lock。多线程的运行都是在同一个JVM之下。应用是分布式集群&#xff0c;属于多JVM的工作环境&#xff0c;JVM之间已经无法通过…

【Golang开源项目】Golang高性能内存缓存库BigCache设计与分析

项目地址 BigCache 是一个快速&#xff0c;支持并发访问&#xff0c;自淘汰的内存型缓存&#xff0c;可以在存储大量元素时依然保持高性能。BigCache将元素保存在堆上却避免了GC的开销。 背景介绍 BigCache的作者在项目里遇到了如下的需求&#xff1a; 支持http协议支持 10…

【RT-DETR改进涨点】为什么YOLO版本的RT-DETR训练模型不收敛的问题

前言 大家好&#xff0c;我是Snu77&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 其中提到的多个版本ResNet18、ResNet34、ResNet50、ResNet101为本人根据RT-…

Linux|centos7操作系统|VMware虚拟机安装水星免驱USB网卡8188gu记录

引言&#xff1a; 最近对于嵌入式系统比较感兴趣&#xff0c;因此&#xff0c;计划先使用VMware workstation虚拟机试一试Linux系统下的网卡驱动安装 这不试不知道&#xff0c;一试吓一跳&#xff0c;发现Linux下的驱动安装还是比较麻烦的&#xff0c;下面将就本次的Linux系统…

详解SpringCloud微服务技术栈:强推!源码跟踪分析Ribbon负载均衡原理、Eureka服务部署

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;详解SpringCloud微服务技术栈&#xff1a;认识微服务、服务拆分与远程调用 &#x1f4da;订阅专栏&#xff1a;微服务技术全家桶…

【LangChain学习之旅】—(6) 提示工程(下):用思维链和思维树提升模型思考质量

【LangChain学习之旅】—&#xff08;6&#xff09; 提示工程&#xff08;下&#xff09;&#xff1a;用思维链和思维树提升模型思考质量 什么是 Chain of ThoughtFew-Shot CoTZero-Shot CoTChain of Thought 实战CoT 的模板设计程序的完整框架Tree of Thought总结 Reference&a…

UE5 伤害数字跳出

学习视频 大体思路&#xff1a; 1.创建一个控件蓝图。 播放动画&#xff0c;K透明度&#xff0c;文本位置。 2.创建一个控件组件。 类默认值中设置。 3.在位置处创建组件实例 自定义事件略。

NVIDIA Isaac Sim 入门教程(一)

系列文章目录 前言 一、 NVIDIA Omniverse™ Isaac Sim 是什么&#xff1f; NVIDIA Omniverse™ Isaac Sim 是一款适用于 NVIDIA Omniverse™ 平台的机器人仿真工具包。Isaac Sim 具有构建虚拟机器人世界和实验的基本功能。它为研究人员和从业人员提供了创建稳健、物理精确的仿…

无法解析服务器的名称或地址/Wsl/0x80072eff/win10 WSL2问题解决Wsl 0x800701bc/Wsl:0x80041002

无法解析服务器的名称或地址 和 Wsl/0x80072eff 1.连VPN&#xff0c;推荐的VPN如下。(如一直显示无法连接&#xff0c;则推荐使用VPN) Anycast加速器 (any4ga.com) 优点&#xff1a;无限GB 缺点&#xff1a;较贵&#xff0c;通过银行卡充值9折后的价格是每月45元左右 …

JVM:双亲委派机制类加载器

JVM&#xff1a;双亲委派机制 1. 例子2. 类加载器总结3. 类加载过程4. 双亲委派模型的执行流程&#xff1a;5. 双亲委派模型的好处 1. 例子 Java运行时环境有一个java.lang包&#xff0c;里面有一个ClassLoader类 我们自定义一个String类在java.lang包下&#xff0c;下面的…

WEB 3D技术 three.js 点光源

本文的话 我们来设置一下点光源 点光源其实最直观的就是可以做萤火虫 也可以做星光 点点的效果 我们可以直接在官网中搜索 Pointlight 大家可以在官网这里看一下 其实 SpotLight 聚关灯中的属性 Pointlight 点光源也有的 我们先编写代码如下 import ./style.css import * a…

MySQL之单表查询

素材&#xff1a; 表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作 等 CREATE TABLE worker ( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL, 工资 float(8,2) NOT NULL, 政治面貌 varchar(10) NO…

【Git】本地仓库管理远程库(GitHub)——clone(下载)、commit(添加到本地仓库)、push(提交到远程仓库)、pull(拉取)操作

目录 使用远程仓库的目的将本地仓库同步到git远程仓库 1.克隆远程仓库(clone)2.新建一个文件3.将工作区的文件添加到暂存区4.将暂存区的文件添加到本地仓库(commit)5.提交(同步)到远程仓库(push)6.远程库拉取到本地库(pull)7.团队协作开发和跨团队协作开发(开源项目) 使用远程…

PTA(浙大版《C语言程序设计(第3版)》题目集

PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集 学习C语言程序设计的PTA题目 目录 PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集) 习题2-1 求整数均值 (10 分)输入格式:…

大型语言模型综述/总结 LLM A Survey of Large Language Models

A Survey of Large Language Model AbstractINTRODUCTIONOVERVIEW背景LLM的新兴能力LLM的关键技术GPT 系列模型的技术演进 大语言模型资源公开可用的模型检查点或 API常用语料库代码库资源 预训练数据收集架构 论文标题&#xff1a;A Survey of Large Language Model 论文地址&…

电子学会C/C++编程等级考试2023年09月(五级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:红与黑 有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。 时间限制:1000 内存限制:65536 输入 包括多…

Linux的SSH远程管理和服务器之间的免密连接

目录 一、远程管理基础 1.ssh协议 2.ssh原理 3、使用ssh协议传输的命令 4.登录方法 二、免密连接 1.免密连接的原理 2.实战 一、远程管理基础 1.ssh协议 ssh协议是基于C/S机构的安全通道协议&#xff0c;通信数据进行加密处理&#xff0c;用于远程管理。 ssh的服务名…

Python文件读写与字符编码详解【第25篇—python基础知识】

文章目录 文件读写和字符编码在Python中的实现一、I/O操作概述二、文件读写实现原理与操作步骤1. 文件读写实现原理2. 文件读写操作步骤 三、文件打开模式四、Python文件操作步骤示例五、文件读取相关方法1. 读取指定长度的内容2. 读取文件中的一行内容3. 遍历打印一个文件中的…

Zookeeper使用详解

介绍 ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、域名服务、分布…

【搭建个人知识库-3】

搭建个人知识库-3 1 大模型开发范式1.1 RAG原理1.2 LangChain框架1.3 构建向量数据库1.4 构建知识库助手1.5 Web Demo部署 2 动手实践2.1 环境配置2.2 知识库搭建2.2.1 数据收集2.2.2 加载数据2.2.3 构建向量数据库 2.3 InternLM接入LangChain2.4 构建检索问答链1 加载向量数据…