快速幂及矩阵快速幂分析及代码实现

news2024/11/17 4:50:48

文章目录

  • 前言
  • 一、认识快速幂
  • 二、快速幂思路及代码
  • 三、矩阵快速幂
    • 3.1、矩阵乘法代码实现
    • 3.2、矩阵快速幂代码实现
  • 参考资料

前言

在学习Acwing c++蓝桥杯辅导课第九讲复杂DP-AcWing 1303. 斐波那契前 n 项和时有使用到矩阵快速幂算法,这里来记录下知识点正好也将快速幂部分也整合下。

当前文章已收录到博客文件目录索引:博客目录索引(持续更新)

一、认识快速幂

快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高

问题引出:7的10次方,怎样算比较快?

原理

快速幂算法的核心思想就是每一步都把指数分成两半,而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,所需要执行的循环次数也变小,而最后表示的结果却一直不会变。

//可以看到由原先的n次倍数相乘之后转变来让运行次数大大减小
3^10=3*3*3*3*3*3*3*3*3*3
3^10=(3*3)*(3*3)*(3*3)*(3*3)*(3*3)
3^10=(3*3)^5
3^10=9^5
9^5=9^4*9^19^5=6561^1*(9^1)

通过使用快速幂,能够将时间复杂度降低为log2N


二、快速幂思路及代码

核心二分思路:拆分为三种情况,①n为奇数。②n为偶数。③n=0。

image-20220418194312084

/**
 * @ClassName 快速幂
 * @Author ChangLu
 * @Date 4/18/2022 7:28 PM
 * @Description 快速幂求解
 */
public class 快速幂 {

    //取模操作(对大素数取模)
    private static final long MOD = 1000000007;

    public static void main(String[] args) {
//        System.out.println(qpow(2, 3));
        System.out.println(qpow2(2, 100000000));
    }

    /**
     * 递归快速幂
     * @param a 实数a
     * @param n 阶数n,三种情况,n=0,n=奇数,n=偶数
     * @return
     */
    public static long qpow(long a, long n){
        if (n == 0){
            return 1;
        }else if ((n & 1) == 1) {  //奇数
            return qpow(a, n -1) * a % MOD;
        }else {
            long temp = qpow(a, n / 2) % MOD;
            return temp * temp % MOD;
        }
    }

    /**
     * 非递归方式
     */
    public static long qpow2(long a, long n) {
        long ans = 1;
        while ( n != 0) {
            if ((n & 1) == 1) { //若是n为奇数
                ans *= a % MOD;
                ans %= MOD;//求模处理
            }
            a *= a % MOD; //这个就表示偶数情况
            a = a % MOD;//求模处理
            n = n >> 1;
        }
        return ans;
    }


}

三、矩阵快速幂

3.1、矩阵乘法代码实现

首先先了解下矩阵乘法:

image-20230129171016240

模板:

//i与j来进行用来定位结果矩阵中的下标  k则是用来使用第i列数字*第j列数字
for (int i = 0; i <= 2; i ++ ) 
  for (int j = 0; j <= 2; j ++ ) 
  	for (int k = 0; k <= 2; k ++ )
  	  c[i][j] += a[i][k] * b[k][j];

测试代码:

import java.util.Arrays;

public class Main {

    static final int[][] a = {
            {1, 2},
            {3, 4}
    };
    static final int[][] b = {
            {3, 1},
            {2, 4}
    };

    //矩阵乘法
    //返回的是a*b矩阵的结果矩阵
    public static int[][] multi(int a[][], int b[][]) {
        int x = a.length, y = b[0].length, z = b.length;
        int[][] ans = new int[x][y];
        for (int i = 0; i < x; i++)
            for (int j = 0; j < y; j++)
                for (int k = 0; k < z; k++)
                    ans[i][j] += a[i][k] * b[k][j];
        return ans;
    }

    public static void main(String[] args) {
        //矩阵乘法
        int[][] c = multi(a, b);
        for (int[] arrs : c) {
            System.out.println(Arrays.toString(arrs));
        }
    }
}

image-20230129172719510


3.2、矩阵快速幂代码实现

若是矩阵为A,来让我们求An此时若是我们可以实现矩阵快速幂,代码模板如下:

//n表示的乘的次数
while (n != 0) {
    //n为奇数情况
	if ((n & 1) == 1) ans = mult(ans, A);
    //n为偶数情况
	mult(A, A);
	n >>= 1;
}

实际案例代码:矩阵快速幂

import java.util.Arrays;

public class Main {

    static final int[][] a = {
            {1, 2},
            {3, 4}
    };
    static final int[][] b = {
            {3, 1},
            {2, 4}
    };

    //矩阵乘法
    //返回的是a*b矩阵的结果矩阵
    public static int[][] multi(int a[][], int b[][]) {
        int x = a.length, y = b[0].length, z = b.length;
        int[][] ans = new int[x][y];
        for (int i = 0; i < x; i++)
            for (int j = 0; j < y; j++)
                for (int k = 0; k < z; k++)
                    ans[i][j] += a[i][k] * b[k][j];
        return ans;
    }

    //矩阵快速幂
    public static int[][] pow_multi(int a[][], int n) {
        int m = a.length;
        //初始化ans结果矩阵
        int ans[][] = new int[m][m];
        for (int i = 0; i < m; i ++) {
            for (int j = 0; j < m; j ++) {
                if (i == j) ans[i][j] = 1;
            }
        }
        //写法基本与整数快速幂一致
        while (n != 0) {
            if ((n & 1) == 1) ans = multi(ans, a);
            a = multi(a, a);
            n >>= 1;
        }
        return ans;
    }

    public static void main(String[] args) {
        //矩阵乘法
        int[][] c = multi(a, b);
        for (int[] arrs : c) {
            System.out.println(Arrays.toString(arrs));
        }
        System.out.println();
        //快速幂
        int[][] d = pow_multi(a, 2);
        for (int[] arrs : d) {
            System.out.println(Arrays.toString(arrs));
        }
    }
}

image-20230129175125566

参考资料

[1]. 蓝桥杯软件类备赛:快速幂和矩阵快速幂

[2]. 「算法小知识」如何计算快速幂(上):快速幂。

[3]. 算法学习笔记(4):快速幂:该文章不错可以学习。

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

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

相关文章

车载以太网 - SomeIP测试专栏 - 详细解析 - 01

对于介绍SomeIP协议&#xff0c;我还是想从最基础的协议解析来&#xff0c;所以今天还是先将SomeIP协议详解给大家列举一下&#xff0c;也方便大家在工作中如果不记得哪些信息随时可以查看学习&#xff0c;也算是留给我自己的笔记吧&#xff0c;毕竟确实容易忘记。 SomeIP数据&…

分布式数据库中间件——Mycat2

一、Mycat2 概述 Mycat是基于java语言编写的数据库中间件&#xff0c;核心功能是分库分表和读写分离&#xff0c;可以将大表水平分割为N个小表。 可以看做为Mysql的数据库服务器&#xff0c;可以用连接Mysql的方式去连接Mycat&#xff0c;端口为8066 二、Mycat的三大作用 2.…

Node 项目中常见的问题及解决方法

1. window和mac下设置NODE_ENV变量的问题 我们都知道在前端项目中会根据不同的环境变量来处理不同的逻辑&#xff0c;在node后端中也一样&#xff0c;我们需要设置本地开发环境、测试环境、 线上环境等&#xff0c;此时有一直设置环境变量的方案是在package.json中的script属性…

Python学习笔记——错误和异常

错误的分类编写程序过程中遇到的错误都分为两类&#xff1a;语法错误与运行时错误。语法错误&#xff1a;当代码不符合Python语法规则时, 在解析过程中会报SyntaxError。运行时错误&#xff1a;即语句或表达式在语法上都是正确的, 但在运行时发生了错误。当程序发生异常时&…

从零搭建完整python自动化测试框架(UI自动化和接口自动化

从零搭建完整python自动化测试框架&#xff08;UI自动化和接口自动化&#xff09; 文章目录 总体框架 PO模式、DDT数据驱动、关键字驱动 框架技术选择 框架运行结果 各用例对应的定义方式&#xff08;PO/DDT&#xff09; 测试执行结果 从零开始搭建项目 一、开发环境搭…

Vue-Vuex

前言 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 库 官网介绍&#xff1a;https://vuex.vuejs.org/zh/ 以下主要讲解的是如何定义与使用&#xff0c;如果还没有对vuex进行了解的话&#xff0c;请先查看官网&#xff0c;了解其功能、用法及用途。 关于vuex&#xff0c…

代码随想录算法训练营第五十二天_第九章_动态规划 | 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

LeetCdoe 121. 买卖股票的最佳时机给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可…

verilog 数字系统设计读书笔记-------持久更新

Verilog模型可以是实际电路的不同级别的抽象。这些抽象的级别和它们所对应的模型类型共有以下5种&#xff1a;系统级、算法级、RTL级、门级、开关级‘bz :表示高阻态&#xff0c; ’bx表示不定值&#xff08;0或1均可&#xff09;include "muxtwo.v" 将文件引进{$ ra…

【Linux】怎么理解进程

✍作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;Liunx系统编程 本文通过冯诺依曼体系结构&#xff08;硬件部分&#xff09;和操作系统&#xff08;软件部分&#xff09;为基础来介绍我们应该如何理解进程&#xff0c;为后续的学习做铺垫。 本文目录一、预备知识1.建…

误差逆传播算法公式理解及推导

前言&#xff1a;公式理解及推导参考自《机器学习》周志华 P101 BP网络 BP网络一般是指由 误差逆传播&#xff08;error BackPropagation, BP&#xff09;算法训练的多层前馈神经网络。 给定训练集 D{(x1,y1)D\left\{\left(\boldsymbol{x}_1, \boldsymbol{y}_1\right)\right…

2023年我的Flag已准备完毕

前言&#xff1a; &#x1f604;作者简介&#xff1a;小曾同学.com,小伙伴们也可以叫我小曾&#xff0c;一个致力于测试开发的博主⛽️ 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。 &#x1f60a; 座右铭&#xff1a…

用力过猛,把服务压挂了?

背景 在刚开始进行压测的时候&#xff0c;我也不知道需要提前分析下压测的QPS目标&#xff0c;也不知道说第一步压测的预估值是多少&#xff0c;结果一下子干上去&#xff0c;就把测试环境的服务给整挂了&#xff0c;然后就迎来了一大波的投诉&#xff08;好惨呐&#xff09…

【6-循环神经网络】北京大学TensorFlow2.0

课程地址&#xff1a;【北京大学】Tensorflow2.0_哔哩哔哩_bilibiliPython3.7和TensorFlow2.1六讲&#xff1a;神经网络计算&#xff1a;神经网络的计算过程&#xff0c;搭建第一个神经网络模型神经网络优化&#xff1a;神经网络的优化方法&#xff0c;掌握学习率、激活函数、损…

基于微信小程序的校园自助打印系统小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.…

GJB 5000B二级-RDM需求开发与管理

一、主要变化情况 新增3项(金色)、合并12->5项(绿色)、修订3项(蓝色) 合并的主要内容 1、合并过程域:原标准中RD与ReqM合并为RDM   需求开发与需求管理的过程活动紧密相关,在全生命周期中不可分割。 2、合并实践条目:精炼实践,聚焦重点   a)ReqM SP1.1“获…

UE运行时动态设置屏幕分辨率

文章目录 1.实现目标2.实现过程2.1 控制台直接输入命令2.2 通过蓝图设置3.参考资料1.实现目标 在UE中以独立进程(Standalone Game)方式启动游戏,并在运行时动态修改游戏窗口的屏幕分辨率大小,如下图所示屏幕大小从1000x800修改为600x400。 2.实现过程 参考文档和资料,通…

微服务服务治理

服务治理什么是服务治理&#xff1f;第一部分 服务注册第二部分 服务发现Nacos(常见注册中心)入门搭建Nacos环境Nacos远程调用实现商品服务的负载均衡什么是负载均衡&#xff1f;手动实现负载均衡利用组件实现负载均衡修改负载均衡策略什么是服务治理&#xff1f; 服务治理是微…

PySpark sql 中一些函数的总结(持续更新)

看到什么函数就记录了&#xff0c;没有什么逻辑关系 spark 中DataFrame 和 pandas的DataFrame的区别 1. F.split() 和 df.withColumn() from pyspark.sql import SparkSession from pyspark.sql import functions as F from pyspark.sql.types import *df spark.sql(sql) sp…

打开Jupyter notebook没有虚拟环境内核

放了个假&#xff0c;今天准备打开anaconda中的jupyter notebook重温一下之前的文档&#xff0c;结果双击Anaconda-Navigator出现了【应用程序“Anaconda-Navigator”无法打开】&#xff0c;想着利用终端也可以操作&#xff0c;于是使用下面命令激活了环境并打开jupter noteboo…

JZ11 旋转数组的最小数字

【答案解析】&#xff1a;暴力破解&#xff1a;遍历数组找出最小值即可 更优思想&#xff1a;采用二分查找&#xff0c;这个题主要分析三种旋转情况[1, 2, 3, 4, 5]&#xff0c;使用中间值与右端进行比较。 1. 中间大于右边[3, 4, 5, 1, 2]&#xff0c;这种情况下&#xff0c;最…