矩阵快速幂

news2024/11/23 15:28:23

要想知道矩阵快速幂,我们先了解一下什么叫快速幂和矩阵乘法


一、快速幂

快速幂算法是用来快速计算指数表达式的值的,例如 210000000,普通的计算方法 2*2*2*2…10000000次,如果一个数字的计算都要计算那么多次的话,那么这个程序一定是失败的。

快速幂思想及实现

快速幂思想其实很简单,就是公式的转换
1、当指数是偶数时,我们可以让指数除以2,底数乘以底数
2、当指数是奇数时,我们可以将指数变为偶数

#include <iostream>
using namespace std;
typedef long long LL;

long long fpow(long long x, long long p)
{
	long long ans = 1;
	//完整代码
	//while (p) {
	//	if (p % 2 == 1) {
	//		ans *= x, p--;
	//	}
	//	else {
	//		p /= 2;
	//		x *= x;
	//	}
	//}

	//精简代码
	while (p) {
		if (p & 1) ans *= x ; //p为奇数
		p >>= 1;
		x *=x;
	}
	return ans;
}
int main()
{
	LL x, p;
	cin >> x >> p;
	cout << fpow(x, p) << endl;
}


二、矩阵乘法

图文演示:

#include <iostream>
#include <algorithm>
using namespace std;

typedef long long int ll;
const int mod = (int)1e9 + 7;
const int N = 1e3;

int a[N][N], b[N][N];
int temp[N][N];
// a = a * b
void MAXMP(int a[][N], int b[][N], int n, int p, int m) //第一个矩阵的行,两个矩阵相同的列行,第二个矩阵的列,
{
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++) temp[i][j] = 0;
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			for (int k = 1; k <= p; k++)
			{
				temp[i][j] = (temp[i][j] + (a[i][k] * b[k][j]) % mod) % mod;
			}
		}
	}
}

int main()
{
	int n, m, p;
	cin >> n >> p >> m; //行 列行 列
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= p; j++) cin >> a[i][j];
	}

	for (int i = 1; i <= p; i++)
	{
		for (int j = 1; j <= m; j++) cin >> b[i][j];
	}

	MAXMP(a, b, n, p, m);

	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++) cout << temp[i][j] << endl;
	}

}

三、矩阵快速幂

        矩阵快速幂,即给定一个矩阵A(m*n)),快速计算A^n。一般来说,矩阵快速幂只会涉及方阵即A(n*n),所以下面以方阵为例。(一般来说,只有方阵存在矩阵幂值,故此时等行等列)

#include <iostream>
#include <algorithm>
using namespace std;

typedef long long int ll;
const int mod = (int)1e9 + 7;
const int N = 1e3;

int a[N][N], res[N][N];
int temp[N][N];

// a = a * b
void MXMP(int a[][N], int b[][N], int n) 
{
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++) temp[i][j] = 0;
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			for (int k = 1; k <= n; k++)
			{
				temp[i][j] = (temp[i][j] + (a[i][k] * b[k][j]) % mod) % mod;
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) a[i][j] = temp[i][j];
	}
}

void PowerMod(int a[][N], int n, int x)//x为次幂,n为矩阵行,m为矩阵行
{
	memset(res, 0, sizeof(res));
	for (int i = 1; i <= n; i++) res[i][i] = 1;//初始化为单位矩阵
	while (x){
		if (x & 1) MXMP(res, a, n);
		MXMP(a, a, n);
		x >>= 1;
	}
}

int main()
{
	int n, x;
	cin >> n >> x;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++) cin >> a[i][j];
	}
	PowerMod(a, n, x);
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++) cout << res[i][j] <<" ";
		cout << endl;
	}
	return 0;
}

四、矩阵快速幂的应用

斐波拉契函数

  例如:斐波那契数列的递推计算的时间复杂度为O ( n ),f[0] = 1,f[1] = 1,f[i] = f[i-1]+f[i-2],(i>1),换成矩阵乘法的形式,即

  利用矩阵乘法和快速幂运算,时间复杂度可达到 O(2^3\ logn)O优于普通的O(n), 其中数字2 为抽象出的矩阵边长 2^32 为矩阵乘法运算的时间,logn为快速幂运算时间。

  注意:实现时为了简便可以把矩阵C的大小设置成等同于矩阵B的大小,空位用0填充

#include <iostream>
#include <algorithm>
using namespace std;

typedef long long int ll;
const int mod = (int)1e9 + 7;
const int N = 1e3;

int a[N][N], res[N][N];
int temp[N][N];
int f[N][N];

// a = a * b
void MXMP(int a[][N], int b[][N], int n) 
{
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++) temp[i][j] = 0;
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			for (int k = 1; k <= n; k++)
			{
				temp[i][j] = (temp[i][j] + (a[i][k] * b[k][j]) % mod) % mod;
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) a[i][j] = temp[i][j];
	}
}

void PowerMod(int a[][N], int n, int x)//x为次幂,n为矩阵行列
{
	memset(res, 0, sizeof(res));
	for (int i = 1; i <= n; i++) res[i][i] = 1;//初始化为单位矩阵
	while (x){
		if (x & 1) MXMP(res, a, n);
		MXMP(a, a, n);
		x >>= 1;
	}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			a[i][j] = res[i][j];
}

int solve(int n)
{
	if (n == 1 || n == 2) return 1;
	a[1][1] = 1, a[1][2] = 1;
	a[2][1] = 1, a[2][2] = 0;

	PowerMod(a, 2, n - 2);

	f[1][1] = 1, f[2][1] = 1;

	MXMP(a, f, 2);

	return a[1][1];
}

int main()
{
	int n;
	cin >> n;
	cout << solve(n) << endl;

	return 0;
}

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

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

相关文章

c++多线程2小时速成

简介 c多线程基础需要掌握这三个标准库的使用&#xff1a;std::thread,std::mutex, andstd::async。 1. Hello, world #include <iostream> #include <thread>void hello() { std::cout << "Hello Concurrent World!\n"; }int main() {std::th…

5.合并两个有序数组

文章目录 题目简介题目解答解法一 &#xff1a;合并后排序解法二&#xff1a;双指针排序 题目链接 大家好&#xff0c;我是晓星航。今天为大家带来的是 合并两个有序数组 相关的讲解&#xff01;&#x1f600; 题目简介 题目解答 解法一 &#xff1a;合并后排序 假设我们要合…

【C++】从零开始认识多态

送给大家一句话&#xff1a; 一个犹豫不决的灵魂&#xff0c;奋起抗击无穷的忧患&#xff0c;而内心又矛盾重重&#xff0c;真实生活就是如此。 ​​​​ – 詹姆斯・乔伊斯 《尤利西斯》 _φ(*&#xffe3;ω&#xffe3;)&#xff89;_φ(*&#xffe3;ω&#xffe3;)&…

期权买方要保证金吗?期权交易保证金怎么计算?

今天期权懂带你了解期权买方要保证金吗&#xff1f;期权交易保证金怎么计算&#xff1f;期权保证金其实就是你在购买期权合约时&#xff0c;作为卖方要付出的那一小笔钱。简单说&#xff0c;就是为了防止你违约&#xff0c;给交易双方一个保障的“小押金”。 期权买方要保证金吗…

软考中级-软件设计师(八)算法设计与分析 考点最精简

一、算法设计与分析的基本概念 1.1算法 算法&#xff08;Algorithm&#xff09;是对特定问题求解步骤的一种描述&#xff0c;有5个重要特性&#xff1a; 有穷性&#xff1a;一个算法必须总是在执行又穷步骤后结束&#xff0c;且每一步都可在又穷时间内完成 确定性算法中每一…

如何做好一个活动策划?

活动策划的关键要素是什么&#xff1f; 首先&#xff0c;要明确一个概念:做活动就是走钢丝&#xff0c;没有保险的高空走钢丝!因为&#xff0c;活动没有“彩排”&#xff0c;只有现场"直播”! 无论什么类型的活动&#xff0c;人数是50人还是2000人&#xff0c;也不论预算…

Parts2Whole革新:多参照图定制人像,创新自定义肖像生成框架!

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; Parts2Whole革新&#xff1a;多参照图定制人像&#xff0c;创新自定义肖像生成框架&#xff01; 引言&#xff1a;探索多条件人像生成的新篇章 在数字内容创作…

用户管理中心——数据库设计用户注册逻辑设计

用户管理中心——数据库设计&用户注册逻辑设计 规整项目目录1. 数据库自动生成器的使用实现基本的数据库操作&#xff08;操作user表&#xff09; 2. 注册逻辑的设计(1) 写注册逻辑(2) 实现(3) 测试代码 3. 遇到的问题 规整项目目录 utils–存放工具类&#xff0c;比如加密…

贪心算法应用例题

最优装载问题 #include <stdio.h> #include <algorithm>//排序int main() {int data[] { 8,20,5,80,3,420,14,330,70 };//物体重量int max 500;//船容最大总重量int count sizeof(data) / sizeof(data[0]);//物体数量std::sort(data, data count);//排序,排完数…

OpenHarmony 实战开发—— refreshlayout 组件开发学习指南~

1. RefreshLayout_harmonyos 功能介绍 1.1. 组件介绍&#xff1a; RefreshLayout_harmonyos 是一款下拉刷新组件 1.2. 手机模拟器上运行效果&#xff1a; 2. RefreshLayout_harmonyos 使用方法 2.1 在目录 build.gradle 下 implementation project(":refreshlayout_ha…

【YoloDeployCsharp】基于.NET Framework的YOLO深度学习模型部署测试平台

YoloDeployCsharp|基于.NET Framework的YOLO深度学习模型部署测试平台 1. 项目介绍2. 支持模型3. 时间测试4. 总结 1. 项目介绍 基于.NET Framework 4.8 开发的深度学习模型部署测试平台&#xff0c;提供了YOLO框架的主流系列模型&#xff0c;包括YOLOv8~v9&#xff0c;以及其系…

Linux 手动部署JDK21 环境

1、下载包&#xff08;我下载的是tar) https://www.oracle.com/cn/java/technologies/downloads/#java21 完成后进行上传 2、检查已有JDK&#xff0c;并删除&#xff08;我原有是jdk8&#xff09; rpm -qa | grep -i java | xargs -n1 rpm -e --nodeps3、清理掉 profile中的j…

PXE 批量安装部署

目录 一、PEX批量部署优点 二、PXE&#xff1a;预启动执行环境 三、搭建PXE远程服务器 要想全自动安装 接下来请看步骤&#xff1a; 一、PEX批量部署优点 规模化&#xff1a;同时装配多台服务器自动化&#xff1a;安装系统 配置各种服务远程实现&#xff1a;不需要光盘&…

代码随想录算法训练营DAY43|C++动态规划Part5|1049.最后一块石头的重量II、494.目标和、474.一和零

文章目录 1049.最后一块石头的重量II思路CPP代码 ⭐️494.目标和回溯算法抽象成01背包问题CPP代码本题总结 474.一和零思路CPP代码 1049.最后一块石头的重量II 力扣题目链接 文章链接&#xff1a;1049.最后一块石头的重量II 视频链接&#xff1a;这个背包最多能装多少&#xff…

Material Studio 计算分子静电力、电荷密度以及差分电荷密度

1.先打开Material Studio导入要计算的分子cif文件或者mol文件&#xff0c;直接Flie-Import 2.高斯几何优化一下结构&#xff0c;参数按照我的设置就行&#xff0c;一般通用&#xff0c;后面出问题再调整 3.点完Run后会跳出很多计算过程&#xff0c;不用管&#xff0c;等他计算完…

30分钟打造属于自己的Flutter内存泄漏检测工具---FlutterLeakCanary

30分钟打造属于自己的Flutter内存泄漏检测工具 思路检测Dart 也有弱引用-----WeakReference如何执行Full GC&#xff1f;如何知道一个引用他的文件路径以及类名&#xff1f; 代码实践第一步&#xff0c;实现Full GC第二步&#xff0c;如何根据对象引用&#xff0c;获取出他的类…

Django框架四-项目

一、项目准备 1.流程与人员 2.需求分析 项目主要页面 归纳项目主要模块 3.架构设计 项目开发模式 项目架构设计

资源管理器CPU占用太高

最近资源管理器经常飙到80%-100%&#xff0c;所以电脑很卡。比如下面的新打开一个文件目录就这样 工具 shexview下载地址 排除 排序 先点Microsoft排序&#xff0c;上面粉色的就是所谓的外部插件 全部禁用 粉色全选->右键->Disable Selected Items &#xff08;看其他…

ZIP压缩输出流(将ZIP文件解压)

文章目录 前言一、ZIP压缩输出流是什么&#xff1f;二、使用介绍 1.使用方法2.实操展示总结 前言 该篇文章相对应的介绍如何使用java代码将各种文件&#xff08;文件夹&#xff09;从ZIP压缩文件中取出到指定的文件夹中。解压流将ZIP文件中的文件以条目的形式逐一读取&#xff…

Java毕业设计 基于SpringBoot vue企业信息管理系统

Java毕业设计 基于SpringBoot vue企业信息管理系统 SpringBoot 企业信息管理系统 功能介绍 员工&#xff1a;登录 个人中心 修改密码 个人信息 会议管理 公告管理 个人计划管理 通讯录管理 外出登记管理 请假管理 上下班打卡管理 管理员&#xff1a;登录 个人中心 修改密码 …