快速幂算法及其拓展

摘要

本文讲解了快速幂算法的定义、复杂度证明及两种实现(递归与非递归),以及它的两个重要拓展:快速幂模M算法和矩阵快速幂。其中矩阵快速幂算法是矩阵求幂问题对整数求幂问题的借鉴,实际应用中对于线性递推式求解能起到强大的效率优化。


快速幂算法

问题引入:求 an(a,nN+)
朴素算法:令ans初始值为1,乘n次a得到 an
朴素算法时间复杂度:O(n)

问题:如果n非常大,比如高达 1015 ,怎么办?
思考:朴素算法哪里可以优化?

朴素算法的特点是,连乘过程中底数始终为 a ,这很不聪明。考虑下例:
a=2,n=15
我们没有必要乘15次2,注意到 15=23+22+21+20 ,不妨将 215 拆分为 223×222×221×220
然后看一下n的二进制形式: 15=(1111)2 .为什么要看这个呢?再举一个例子。

a=2,n=6
26=222×221 ,而 6=(110)2

发现什么规律?
观察发现,当n的第i位(从低到高,i>=0)为1时, an 的拆解表达式里就要乘上一项 a2i .

于是我们有了朴素算法改进的思路:逐位判断幂次n的二进制位是否为1,若是,给答案乘上一个 a2i .
改进后的算法的伪代码描述如下:

a, n, ans;
ans=1;
while n>0
    a = a*a;
    if n%2
        ans = ans*a;
    n = n/2;

这个算法的时间复杂度是多少呢?很显然,它取决于n的二进制形式有多少位,因此 T(n)=log2(n)=O(logn) .这就是快速幂算法。

其实快速幂算法还可以递归实现,因为:
当n为偶数时, an=(an/2)2
当n为奇数时, an=(an/2)2×a
边界条件:当n=1,答案为 a
C语言描述如下:

int quick_power(int a, int n)
{
    if(n == 1) return a;
    int x = quick_power(a, n/2);
    long long ans = (long long)x*x;
    if(n%2) ans *= a;
    return (int)ans;
}

代码中加入了防溢出处理,用快速幂算法的时候比较容易犯的一个错误就是忘了考虑溢出,因此在使用的时候要看清楚数据范围,估算一下答案上界。另外,快速幂算法不推荐用递归实现,因为非递归版本不但代码也很简洁,而且效率还更优。

拓展一:快速幂模M算法

有时候所求幂的结果可能很大,于是问题要求对结果模上一个数M。我们只需要在原来算法的基础上运用一下模运算的性质即可。所谓模运算性质是指以下两条:
ni=1ai mod M=(ni=1ai mod M)mod M
ni=1ai mod M=(ni=1ai mod M)mod M
算法非递归实现的伪代码描述为

a, n, ans, M;
ans=1;
while n>0
    a = a*a % M;
    if n%2
        ans = ans*a % M;
    n = n/2;

拓展二:矩阵快速幂算法

快速幂算法解决的是整数求幂的问题,而矩阵快速幂解决的是矩阵求幂问题,两者没有本质的区别。如果用C++实现,我们只要定义一个矩阵类,然后重载一下乘法运算符,原先的快速幂算法几乎不需要改变。
矩阵快速幂常常用于线性递推式的加速。以下仅举一例。

快速求斐波那契数列第n项

对于这个问题,普通求法的复杂度是O(n),现在我们用矩阵快速幂将它优化到O(logn).
首先,将递推式 f(n)=f(n1)+f(n2) 改写成矩阵形式

[f(n)f(n2)f(n1)f(n3)]=[f(n1)f(n3)f(n2)f(n4)][1110]

进而得到
[f(n)f(n2)f(n1)f(n3)]=[f(4)f(2)f(3)f(1)][1110]n4

接下来,用矩阵加速算法求出 [1110]n4 ,再做一次矩阵乘法,所得矩阵的(0,0)元素就是最终结果。

对于更一般的线性递推式,构造其加速矩阵的方式超出了本文的论述范围,在此省略。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值