C++快速幂详解
快速幂
关于快速幂这一块还是需要做一个总结,写一篇博客捋捋思路,加深理解。
为什么要用快速幂?
例如:现在有一个题目让你求   ,你可能觉得很简单啊,来一个for循环,循环b-1次就行了。但是如果b非常大的情况下,那这个做法是非常低效的,时间复杂度大致为 O(b)。
当用快速幂之后,时间复杂度为O(logn)。
快速幂例子
例如我们用快速幂求 。
将指数拆分能够得到如下的结果。 
学过进制转换看到11拆开的样子肯定会很眼熟,其实这里就是跟二进制有关。
11的二进制为1011 , 
这样一来,我们求就不需要算10次了,现在三次就够了。 
到这里以后,我们可能会觉得后边的这三项似乎不好求。
不着急,我们先上代码。
int poww(int a,int b){
    int ans=1,base=a;
    while(b!=0){
        if(b&1!=0)
          ans*=base;
        base*=base;
        b>>=1;
  }
    return ans;
}代码短小精悍,但是,我还是不太建议刻意去记它,容易忘。理解之后,自然就记住了。
我们将 带入代码走一遍或许你就能够理解了。
其实程序就是自左到右求那三项的值。
上边我们已经知道11的二进制为1011
程序参数a = 2,b =11
ans =1,base = 2
到if判断处,11最后一位明显是1,那么我们就需要与结果变量res相乘。
其实,这里的相乘的就是 ,乘完之后res = 2.
到第六行代码处,base自乘。这一步我给大家详细解释一下:
base*base = , , ,
有没有发现一个问题,每次自乘的结果如下:
我们换种写法你会更明白:
你会发现和上边我们要求的一样。
无非是base = 2。
b >>= 1右移一位,他的作用是将1011变成101–>10–>1
当b的最后一位为0时,不乘base,为1的时候成base。
这样我们能够让res乘上上边的三项,而不乘上2^{2^2}。
其实就是根据b的二进制来判断是否乘上二的阶乘。
如果b最后一位为1,也就是说对b有贡献,所以我们结果乘上base。
否则,我们结果不需要乘base,但是base需要自乘,因为二进制位中左边的权重更大一些。
矩阵快速幂,他的思想和快速幂的思想是一样的。无非就是 底数变为矩阵了。所以你只需定义一下矩阵的乘法即可。

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号