快速幂算法详解

快速幂算法详解

什么是快速幂算法?

快速幂算法,顾名思义,是一种快速求解幂值的方法,之前我们已经探讨过对时间复杂度的分析,通过之前的分析,我们了解了代码的运行速度对代码的优劣影响,我们在设计算法时,考虑时间复杂度至关重要。

快速幂算法可以简化幂的求值速度,将原本的暴力求法的时间复杂度O(n)降低为O(logn),大大降低了代码的运行速度。

求210000000000000000000…

这里我们以求2的1000000次方的值为例,很多人一看到这道题目,觉得并不是很难,一个for循环就解决了,也就是普通的暴力解法,暴力解法如下:

暴力解法

## 暴力求幂

A = 2
B = 1000000
result = 1
for i in range(B):
    result = result*A

print(result)

很明显,当幂值特别大的时候,这个“暴力”求解需要消耗巨大的时间,时间复杂度O(n)

快速幂的思路

我们来举一个例子,例如 910

根据幂的运算法则,910 = (92)5 = (9*9)5

于是乎我们似乎发现一个可以降低时间复杂度的方法,因为原本需要乘10次的运算现在变成了只需要乘5次。

但是这个法则只适用于偶数幂,如果幂变成了奇数,如上面这个5的情况,该怎么办呢?

很显然,我们可以将奇数幂次减一变成偶数幂,把幂次为奇数的底数的一次方乘在右边,将分离出来的偶次幂继续重复以上的操作


910 = (92)5 = (92)4 * (92)1

(92)4 = (81)4 把幂次除以2,底数执行平方操作= (812)2

(812)2 = (6561)2

(6561)2 = (43046721)1

此时,幂次又变成了一个奇数,为1,按照上面的方法,我们继续把幂次为奇数的底数的一次方,即(43046721)1拿出来,拿出来以后此时的指数已经变为了0,代表着对偶次幂的重复操作结束。于是我们可以观察到

910 = (92)5 = (92)4 * (92)1 = (812)2 * (92)1 = (6561)2 * (92)1 = (43046721)1 * (92)1

于是乎,快速幂算法提供了这样一个简便的解决思路:

当幂%2==0,也就是当幂为偶数时,根据幂的运算法则,我们可以将幂除以2,然后底数进行平方操作,值保持不变。

当幂%2= =1,也就是当幂为奇数时,将幂为奇数的底数保存起来,再对幂-1,重复上面的操作。

最后的结果就是将幂为奇数的底数综合相乘。

快速幂解法

快速幂解法如下:

A = 2
B = 1000000

def fastpower(base,power):
    result = 1
    while(power>0):
        if (power%2==0):
            base = base*base
            power/=2
        else:
            result = result*base
            power-=1
            power/=2
            base = base*base
    return result


fastpower(A,B)
print(fastpower(A,B))

时间复杂度O(logn)

回到之前,往往不会让你求21000000000000000000000000000000000000…

在日常中,往往都不会叫你算这么大的一个数字,这么大的数字并不是计算机算不出,而是因为这个数字已经大到计算机(语言)已经装不下了。

取余运算法则

所以在使用或者是比赛当中,往往会叫你求某个大数的个位数,后两位数,后三位数等等。

但是我们整体的结果都得不出,更不用说求这个数的某个部分了,所以我们要从前面运算的时候就开始着眼解决这个问题。

根据取余运算法则,我们知道

(a*b)%x = [(a%x) *(b%x)]%x
(a+b)%x = [(a%x) +(b%x)]%x
(a-b)%x = [(a%x) -(b%x)]%x

求21000000的后三位

将上面的算法在每次运算的时候取余即可

代码如下:

A = 2
B = 1000000

def fastpower(base,power):
    result = 1
    while(power>0):
        if (power%2==0):
            base = base*base%1000
            power/=2
        else:
            result = result*base%1000
            power-=1
            power/=2
            base = base*base%=%1000
    return result


fastpower(A,B)
print(fastpower(A,B))

总结

快速幂算法可以将求幂解法的时间复杂度下降,将时间复杂度从O(n) 将为 O(logn),如果n的取值(幂的取值)足够大,时间消耗将大大减少。

同时,求余运算规则也要熟记,可以让我们无需得出总体结果的情况下得出总体结果的余数

你可能感兴趣的:(学习笔记,算法,python,开发语言)