如何快速算出一个数的n次方?

简介: 先计算存储下来再求值,不失为一种好方法;但亦可以在计算 的同时判断 分解为 的幂(即转为 进制)后是否含 ,边计算边乘。形式化地,对于 位,其代表的幂 为 ()。这样,我们由低位向高位计算,每次将底数平方即可。下面两份伪代码,分别对应这种方法的如上两种实现。

本文主要讲解平方求幂(快速幂)相关,凡涉及大整数,都会进行对定值取模等处理,所以存储越界导致的错误、位数过多导致的单次运算缓慢的问题,不在考虑范围之内。


在许多地方常被用到,如Hash 相关、费马小定理、进制转换等。

一般来说,我们要求a的n次方 ,只需要将  a乘 n 次即可,时间复杂度为2YGYEK2LG1LWJ%(E0DZCR)A.png

但有时, n极大,这种方法需要的时间开销是不可接受的。

比如,求 C~S`1K0K[M8UQO2M@SG6~ER.png

如果我们直接计算多个这样的式子,至少在目前主流计算机中,所用时间以分钟计。

我们考虑如何优化对 a的n次方 的计算。



JD(T}09[%1S[D)19T5SM`DA.png



 640.jpg

[6}XR47FSCO@9SE6)ISTETE.png

这样我们就可以写出一份递归的伪代码:

function power(a, n):
 if n = 0 then return 1
 t := power(a, (n - n mod 2) / 2)
 if n mod 2 = 1
 then: return t^2 * a
 else: return t^2

每次将数据规模缩小为原来的一半,这种方法的时空复杂度是 [DTO72EKU_JVDXOR7$B_3~7.png

LXSYH_7~3J7P2BSS({(%28L.png



OJ)})DZBN4G@~LIJEYG)$HV.pngOJ)})DZBN4G@~LIJEYG)$HV.pngLXSYH_7~3J7P2BSS({(%28L.pngLXSYH_7~3J7P2BSS({(%28L.png

function power(a, n):
 pow[0...log n], pow[0] := 1
 for i: 1 to inf
  if (2^i > n) break
  else pow[i] = pow[i - 1]^2
 res := 1
 for i: 1 to inf
  if (2^i > n) break
  else:
   if (n bitand 2^i) res = res * pow[i]
 return res
# n bitand 2^i 可理解为 n 在二进制表示下含 2^i 位
function power(a, n):
 res := 1, p := a
 while n > 0:
  if (n bitand 1) then res = res * a
  p = p^2, n = n >> 1
 return res
# bitand 表示按二进制位与,>> 表示按二进制位右移(可理解为除以 2 下取整)。


J%JU%DX0O3I~H%INTVJ`B7R.png

 

HC{~`795K9%(}J2R$4IX6[U.png

function times(a, b, m):
 if b = 0 then return 0
 t := times(a, (b - b mod 2) / 2, m)
 if b mod 2 = 1
 then: return ((t + t) mod m + a mod m) mod m
 else: return (t + t) mod m

同样地,也可以对  进行二进制拆分。

function power(a, b, m):
 res := 0
 while b > 0:
  if (b bitand 1) then res = (res + a) mod m
  a = (a + a) mod m, b = b >> 1
 return res
# bitand 表示按二进制位与,>> 表示按二进制位右移(可理解为除以 2 下取整)。

这样,我们用 FMK~RRCAE`CFK{Y%RQ(}VP3.png 的时间复杂度算出了大数乘积取模的值。俗称龟速乘


事实上,平方求幂的思想,在任何具有结合律的、参与运算的数据相同的运算中,都可以使用。

如矩阵乘法等。

好了,快速求幂的方法就讲到这里,如果对你有哦帮助,欢迎点赞哦~~


相关文章
|
JSON Java Maven
如何批量查询自己的CSDN博客质量分
如何批量查询自己的CSDN博客质量分
673 0
|
11月前
|
API C++
甩开卡顿!HarmonyOS丢帧问题超详细拆解手册
这是一本针对HarmonyOS丢帧问题的超详细调优指南,从渲染流水线原理到实战优化全面解析。文章拆解了应用侧、Render Service和屏幕显示三大核心模块,结合60Hz/90Hz/120Hz帧率要求,深入分析卡顿原因。通过四步法(识别、录制、定位、优化),提供核弹级性能优化方案,涵盖列表卡顿、动画掉帧、布局臃肿等常见问题,并总结避坑圣经,助你轻松甩开卡顿,打造丝滑体验!
|
网络协议 Android开发 开发工具
国内常用的Android镜像下载地址(附教育网主要镜像站)
终于建了一个自己个人小站:https://huangtianyu.gitee.io,以后优先更新小站博客,欢迎进站,O(∩_∩)O~~ Android developer 最新国内镜像:http://wear.
23783 0
|
8月前
|
Java 关系型数据库 数据库
Healenium Java使用手册
许多文章都介绍healenium Java,但是都没有讲透,下面进行详细介绍。Healenium分为服务器端和客户端,必须二者都配好才可以运转
345 5
|
11月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
431 1
|
边缘计算 人工智能 5G
5G 组网模式:NSA 与 SA 的比较与应用
5G 组网模式:NSA 与 SA 的比较与应用
8114 1
|
存储 C语言
数据结构基础详解(C语言): 栈与队列的详解附完整代码
栈是一种仅允许在一端进行插入和删除操作的线性表,常用于解决括号匹配、函数调用等问题。栈分为顺序栈和链栈,顺序栈使用数组存储,链栈基于单链表实现。栈的主要操作包括初始化、销毁、入栈、出栈等。栈的应用广泛,如表达式求值、递归等场景。栈的顺序存储结构由数组和栈顶指针构成,链栈则基于单链表的头插法实现。
2090 3
|
Linux 开发工具 git
pip的常用命令和常见问题的解决
当使用pip命令安装Python包时,有时候可以通过使用镜像地址来加速下载速度或解决访问限制的问题。以下是一些常用的pip命令和常见的镜像地址:
2653 3
|
存储 JSON 测试技术
Python中最值得学习的第三方JSON库
Python中最值得学习的第三方JSON库
615 0

热门文章

最新文章