1.定义

是一种简单而有效的小算法,它可以以O(logN)的时间复杂度计算乘方。

2.递归快速幂

递归公式

2.1实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
func Qpow(a int, n int) int {
	if n == 0 {
		return 1
	} else if n%2 == 1 {
		return Qpow(a, n-1) * a
	} else {
		tmp := Qpow(a, n/2)
		return tmp * tmp
	}
}

2.2问题

数据大时的溢出问题

3.非递归快速幂

示例

将n的二进制形式拆解,对应相关位置1则乘上对应的数值,得到结果

3.1实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func Qpow2(a int, n int) int {
	ans := 1
	for n != 0 {
		if n&1 > 0 {
			ans *= a
		}
		a *= a
		n >>= 1
	}
	return ans
}

3.2注意

数据大时的溢出问题

4.快速幂的拓展

上面所述的都是整数的快速幂,但其实,在算 an时,只要a的数据类型支持乘法且满足结合律,快速幂的算法都是有效的。矩阵、高精度整数,都可以照搬这个思路。

4.1模板

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
//泛型的非递归快速幂
template <typename T>
T qpow(T a, ll n)
{
    T ans(1); // 这里可能要根据构造函数修改
    while (n)
    {
        if (n & 1)
            ans = ans * a; // 这里就最好别用自乘了,不然重载完*还要重载*=,有点麻烦。
        n >>= 1;
        a = a * a;
    }
    return ans;
}

5.参考

  1. 知乎·快速幂