基础算法--快速幂

0 阅读2分钟

快速幂


快速幂是什么

快速幂,顾名思义就是快速地计算出一个幂值,比如求5n5^{n}。 如果我们限定在一秒钟内算出,如果我们简单地循环n次,那么n最多为10810^8,而且时间复杂度为O(n),也比较慢。

对于5 * 5 * 5 * 5 * 5 * ... * 5,我们可以这样考虑,我们两两分组,化为(5 * 5)* (5 * 5)* ... * (5 * 5)。这样分组以后,我们发现还可以继续分下去(5 * 5 * 5 * 5) * ... * (5 * 5 * 5 * 5),然后还可以继续分下去... 当然,有的时候n并不一定是2t2^t这种形式,但是所有的正整数都可以写成2t2^t相加的形式(其实就是转换二进制),例如19 = 16 + 2 + 1。显然时间复杂度为log2(n)\log_2(n)

下面是一个简单的代码演示:

int res;
while(x != 0){
	if(x % 2 == 1){
		res = res * a;
	}
	x = x / 2;
	a = a * a;
}
return res;

快速幂作为一种数据处理方式,一般不会单独出题,而是作为题目中的一个中间步骤。 下面我们一起来看一道模板题~

快速幂.png

#include <iostream>
#include <cmath>
using namespace std;
long long a, b, p, x, n;
long long ans = 1;

int main(){
    cin >> a >> b >> p;
    x = b;
    n = a;
    while(x != 0){
        if(x % 2 == 1){
            ans = (ans * n) % p;
        }
        x /= 2;
        n = (n * n) % p;
    }
    ans = ans % p;
    printf("%lld^%lld mod %lld=%lld", a, b, p, ans);
    return 0;
}

这道题虽然是先让你算出答案后求模p,但是我们如果这样做,会发现会报一堆的WA,这是因为我们在中间的运算过程中,数值范围超出了long long。 那么该怎么办呢?告诉大家一个结论:任意一个数x,有x % p = (x % p) % p。所以我们在每一次循环中,都可以对ans和n进行模p操作,最后的答案也是一样的,而且不会超出范围