Java实现快速幂算法详解

Java实现快速幂算法详解

快速幂算法(Power Mod)可用来求解形如$a^b\%c$的表达式,其中$a$、$b$和$c$均为正整数。快速幂算法可通过将$b$的二进制分解,以分治的方式加速幂数的计算。

算法流程

  1. 将幂数$b$转化为二进制数
  2. 遍历二进制数中每一位,从高位到低位,若该位上的二进制数字为1,则将当前幂数乘上底数$a$,否则幂数不变。
  3. 将所得的幂数对$c$取模,得到结果

实现代码

public static int powerMod(int a, int b, int c) {
    int res = 1;
    a = a % c;
    while (b > 0) {
        if ((b & 1) == 1) {
            res = (res * a) % c;
        }
        b >>= 1;
        a = (a * a) % c;
    }
    return res;
}

在代码中,a为底数,b为幂数,c为模数。首先将底数a对模数c取模,避免幂数过大导致计算过程中溢出。接下来进入循环,每次移位操作等价于将当前幂数除以2,检查其二进制位最低位。若该二进制位为1,则将结果乘上当前的底数,否则不变。随后将底数自乘,将幂数右移1位,重复上述步骤,直到幂数为0. 最后返回结果。

示例

下面通过两个示例说明快速幂算法的使用方法。

示例1

将$2^{10} \mod 5$的值计算出来。其中,$a=2,b=10,c=5$。

按照快速幂算法的步骤,将$10$转化为二进制数$1010$,从高位到低位遍历,结果为:

  • 当第一位为1时,取$2$本身,此时结果为$2$
  • 当第二位为0时,不变,此时结果为$2$
  • 当第三位为1时,取$2^4$的值,即$16$,对$5$取模后的结果为$1$
  • 当第四位为0时,不变,此时结果为$1$

最后得到$2^{10} \mod 5 = 1$

示例2

将$3^{456789} \mod 100$的值计算出来。其中,$a=3,b=456789,c=100$。

按照同样的步骤,将$456789$转化为二进制数$1110110011000110101$,从高位到低位遍历,结果为:

  • 当第一位为1时,取$3$本身,此时结果为$3$
  • 当第二位为0时,不变,此时结果为$3$
  • 当第三位为1时,取$3^4$的值,即$81$,对$100$取模后的结果为$81$
  • 当第四位为0时,不变,此时结果为$81$
  • 当第五位为1时,取$3^8$的值,即$6561$,对$100$取模后的结果为$61$
  • 当第六位为0时,不变,此时结果为$61$
  • 当第七位为0时,不变,此时结果为$61$
  • 当第八位为1时,取$3^{64}$的值,即$150094635296999121$,对$100$取模后的结果为$21$
  • 当第九位为1时,取$3^{128}$的值,即$4611686018427387904$,对$100$取模后的结果为$64$
  • 当第十位为1时,取$3^{256}$的值,即$1063873589237165248$,对$100$取模后的结果为$44$
  • 当第十一位为0时,不变,此时结果为$44$
  • 当第十二位为1时,取$3^{2048}$的值,即$3545029986111908895090048$,对$100$取模后的结果为$56$
  • 当第十三位为0时,不变,此时结果为$56$
  • 当第十四位为1时,取$3^{16384}$的值,即$655630285178720326763184923104$,对$100$取模后的结果为$36$
  • 当第十五位为0时,不变,此时结果为$36$
  • 当第十六位为1时,取$3^{131072}$的值,即$48661191875666868481...6432991824$,对$100$取模后的结果为$96$
  • 当第十七位为1时,取$3^{262144}$的值,即$23626472274681353693...9890982400$,对$100$取模后的结果为$16$
  • 当第十八位为0时,不变,此时结果为$16$
  • 当第十九位为1时,取$3^{524288}$的值,即$669381122094400496394...664339200$,对$100$取模后的结果为$96$
  • 当第二十位为1时,取$3^{1048576}$的值,即$44612008135508454900481531264...1$,对$100$取模后的结果为$36$
  • 当第二十一位为0时,不变,此时结果为$36$
  • 当第二十二位为1时,取$3^{2097152}$的值,即$55535850279941600865386...583003463424$,对$100$取模后的结果为$96$
  • 当第二十三位为0时,不变,此时结果为$96$
  • 当第二十四位为1时,取$3^{4194304}$的值,即$30880391046625326617429...489089563904$,对$100$取模后的结果为$56$
  • 当第二十五位为0时,不变,此时结果为$56$
  • 当第二十六位为1时,取$3^{8388608}$的值,即$89671244029286034209171382292444031916110...412652032$,对$100$取模后的结果为$16$
  • 当第二十七位为0时,不变,此时结果为$16$
  • 当第二十八位为1时,取$3^{16777216}$的值,即$804357544123133804235070328155150197684...465206784$,对$100$取模后的结果为$56$
  • 当第二十九位为1时,取$3^{33554432}$的值,即$5757218682652774236...5507520564736000$,对$100$取模后的结果为$96$
  • 当第三十位为0时,不变,此时结果为$96$
  • 当第三十一位为1时,取$3^{67108864}$的值,即$324518553658426726783589...665610765209600$,对$100$取模后的结果为$16$

最后得到$3^{456789} \mod 100 = 16$

结语

快速幂算法可以有效地解决大数求幂的问题,其时间复杂度为$O(logn)$,可以有效地减少计算时间。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java实现快速幂算法详解 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • JSP Servelet 数据源连接池的配置

    JSP Servlet数据源连接池的配置需要完成以下步骤: 第一步:导入数据库驱动包 在项目中的WebContent/WEB-INF/lib目录下,将数据库驱动包导入,例如MySQL数据库的驱动包mysql-connector-java-8.0.16.jar。 第二步:在web.xml文件中配置数据源连接池 在web.xml文件中,新增以下内容: <r…

    Java 2023年6月15日
    00
  • Mybatis plus多租户方案的实战踩坑记录

    Mybatis plus多租户方案的实战踩坑记录 什么是多租户 多租户,即多租户架构,是一种软件架构模式,指的是多个客户(租户)共用相同的软件应用系统、数据库和服务器等资源,并且每个租户数据是彼此独立,系统中一个租户的数据不能被其他租户访问。 Mybatis plus多租户 Mybatis plus是Mybatis的增强版,提供了多租户的支持,可以通过配置自…

    Java 2023年6月16日
    00
  • springboot配置mybatis和事务管理方式

    下面是一份关于配置Spring Boot中MyBatis和事务管理的完整攻略,包含两个示例。 一、配置MyBatis和数据库 首先,需要在pom.xml文件中添加MyBatis和数据库依赖 <!– MyBatis依赖 –> <dependency> <groupId>org.mybatis.spring.boot&lt…

    Java 2023年5月20日
    00
  • Java实现简单字符生成器代码例子

    下面我就来详细讲解Java实现简单字符生成器代码的攻略。 步骤一:了解需求 在开始编写代码之前,首先要明确这个代码的需求。我们需要编写一个简单的字符生成器,根据指定的规则生成一定数量的字符并输出。 步骤二:编写基础代码 在开始编写功能代码之前,我们要先编写一些基础代码,如获取用户输入的信息、生成指定范围内的随机数等。下面是代码示例: import java.…

    Java 2023年5月18日
    00
  • (starters)springboot-starter整合阿里云datahub方式

    完整攻略:Spring Boot整合阿里云DataHub 一、前置条件在开始整合之前,需要先确保以下几个条件: 阿里云账号及DataHub服务我们需要一个已开通DataHub服务的阿里云账号,假设我们已有一个名为”test-datahub”的DataHub项目。 工具准备a) Maven及Java IDE(本文以Intellij IDEA为例)b) 阿里云S…

    Java 2023年5月20日
    00
  • Spring Boot启动过程完全解析(一)

    下面是对《SpringBoot启动过程完全解析(一)》的详细讲解: 1. SpringBoot的启动过程 在SpringBoot启动过程中,主要涉及到以下几个步骤: 调用SpringApplication.run()方法启动应用程序 根据相应的配置加载ApplicationContext上下文 完成自动装配 启动嵌入式Web服务器 对于每一步的详细说明,请阅…

    Java 2023年5月15日
    00
  • 详解Spring Boot 使用Java代码创建Bean并注册到Spring中

    这里我们将分步骤地详解如何使用Java代码创建Bean并注册到Spring中。 步骤一:创建Bean 我们要创建一个简单的Java类,并使用@Component注解将其标记为Spring Bean。示例代码如下: import org.springframework.stereotype.Component; @Component public class …

    Java 2023年5月19日
    00
  • 浅谈java中unmodifiableList方法的应用场景

    浅谈Java中unmodifiableList方法的应用场景 在Java集合框架中,有一种叫做unmodifiableList的方法可以创建一个只读的List集合,即使尝试对该List进行写操作也会抛出UnsupportedOperationException异常。本篇文章将详细讲解unmodifiableList方法的应用场景。 1. 为何需要只读List…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部