快速幂与矩阵快速幂

一、快速幂

1.背景

快速幂其实是一种用于快速计算出 x n x^n xn的算法,其中指数n比较大。

2.对比

  • 传统求幂算法:时间复杂度为O(指数n)
  • 快速幂算法:核心思想是每一步都把指数分成两半,而相应的底数做平方运算,这样不仅能把非常大的指数给不断变小,所需要执行的循环次数也在变小,而最后的结果却一直不会变。

3.快速幂的理解

①从二进制的角度进行理解

对于任意的十进制整数n,假设其二进制表示为“ b m . . . b 3 b 2 b 1 b_m ... b_3 b_2 b_1 bm...b3b2b1”,则有二进制转十进制: n = 2 0 b 1 + 2 1 b 2 + 2 2 b 3 + . . . + 2 m − 1 b m n = 2^0b_1+2^1b_2+2^2b_3+...+2^{m-1}b_m n=20b1+21b2+22b3+...+2m1bm
从而有x的二进制展开为: x n = x 2 0 b 1 + 2 1 b 2 + 2 2 b 3 + . . . + 2 m − 1 b m = x 2 0 b 1 ⋅ x 2 1 b 2 ⋅ x 2 2 b 3 ⋅ . . . ⋅ x 2 m − 1 b m x^n = x^{2^0b_1+2^1b_2+2^2b_3+...+2^{m-1}b_m}=x^{2^0b_1}·x^{2^1b_2}·x^{2^2b_3}·...·x^{2^{m-1}b_m} xn=x20b1+21b2+22b3+...+2m1bm=x20b1x21b2x22b3...x2m1bm
根据上述的推导,可以把计算 x n x^n xn转化成解决以下两个问题:

  • 计算 x 2 0 , x 2 1 , x 2 2 , . . . , x 2 m − 1 x^{2^0},x^{2^1},x^{2^2}, ... ,x^{2^{m-1}} x20,x21,x22,...,x2m1:循环赋值 x = x 2 x = x^2 x=x2即可
  • 获取二进制各位 b 1 , b 2 , b 3 , . . . , b m b_1,b_2,b_3,...,b_m b1,b2,b3,...,bm的值:循环执行如下的操作

n&1(与操作):判断二进制位的最后一位是否为1
n>>1(移位操作):n右移一位(可理解为删除二进制位的最后一位)

因此,应用以上操作,可在循环中依次计算 x 2 0 , x 2 1 , x 2 2 , . . . , x 2 m − 1 x^{2^0},x^{2^1},x^{2^2}, ... ,x^{2^{m-1}} x20,x21,x22,...,x2m1的值,并将这些值相乘即可。

②从二分法的角度进行理解

快速幂实际上是二分思想的一种应用。
二分推导: x n = x n / 2 x^n = x^{n/2} xn=xn/2 · x n / 2 x^{n/2} xn/2,若要令 n / 2 n/2 n/2为整数,则需要分n为奇数和偶数两种情况:

  • 当n为偶数: x n = ( x 2 ) n / / 2 x^n = (x^2)^{n//2} xn=(x2)n//2
  • 当n为奇数: x n = x ⋅ ( x 2 ) n / / 2 x^n = x · (x^2)^{n//2} xn=x(x2)n//2,会比多出一项x

根据二分推导,可以通过循环 x = x 2 x = x^2 x=x2的操作,每次把幂从n降为n//2,直至将幂降为0。

设sum=1,设初始状态 x n = x n ⋅ s u m x^n = x^n · sum xn=xnsum。在循环二分的时候,当n为偶数,底数由 x x x变为 x 2 x^2 x2,指数 n n n变为 n / / 2 n//2 n//2;当n是奇数时, s u m = s u m ∗ x sum = sum * x sum=sumx底数由 x x x变为 x 2 x^2 x2,指数 n n n变为 n / / 2 n//2 n//2

算法执行流程如下:

  • 当x==0时:直接返回0
  • 初始化sum=1
  • 当n < 0:把问题转化为n >= 0的范围内,即x = 1/x,n = -n
  • 循环计算(当n == 0结束循环):当n&1 == 1,则sum *= x —>x = x^2 —>n >> 1

二、矩阵快速幂

矩阵快速幂实际上就是将快速幂算法里的数字换成矩阵,

矩阵快速幂算法 = 矩阵乘法 + 快速幂算法

应用实例1:斐波那契数列— f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n1)+f(n2)
[ f ( n ) f ( n − 1 ) ] = [ 1 1 1 0 ] [ f ( n − 1 ) f ( n − 2 ) ] = . . . = [ 1 1 1 0 ] n − 1 [ f ( 1 ) f ( 0 ) ] \begin{gathered} \begin{bmatrix} f(n) \\ f(n-1) \end{bmatrix} = \begin{bmatrix} 1&1 \\ 1&0 \end{bmatrix}\begin{bmatrix} f(n-1) \\ f(n-2) \end{bmatrix}=...= \begin{bmatrix} 1&1 \\ 1&0 \end{bmatrix}^{n-1}\begin{bmatrix} f(1) \\ f(0) \end{bmatrix} \quad \end{gathered} [f(n)f(n1)]=[1110][f(n1)f(n2)]=...=[1110]n1[f(1)f(0)]

应用实例2: f ( n ) = a f ( n − 1 ) + b f ( n − 2 ) + c f(n) = af(n-1) + bf(n-2)+c f(n)=af(n1)+bf(n2)+c
[ f ( n ) f ( n − 1 ) c ] = [ a b 1 1 0 0 0 0 1 ] [ f ( n − 1 ) f ( n − 2 ) c ] = . . . = [ a b 1 1 0 0 0 0 1 ] n − 1 [ f ( 1 ) f ( 0 ) c ] \begin{gathered} \begin{bmatrix} f(n) \\ f(n-1)\\c \end{bmatrix} = \begin{bmatrix} a&b&1 \\ 1&0&0 \\ 0&0&1 \end{bmatrix}\begin{bmatrix} f(n-1) \\ f(n-2) \\ c\end{bmatrix}=...= \begin{bmatrix} a&b&1 \\ 1&0&0 \\ 0&0&1 \end{bmatrix}^{n-1}\begin{bmatrix} f(1) \\ f(0) \\ c\end{bmatrix} \quad \end{gathered} f(n)f(n1)c=a10b00101f(n1)f(n2)c=...=a10b00101n1f(1)f(0)c

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值