快速幂算法的原理及实现

幂运算,即次方运算,例如计算 10^{8}的值即是幂运算,在实现的时候我们往往是这样写的:

int __pow(int a,int b){
    int ans = 1;
    while(b--){
        ans *= a;
    }
    return ans;
}

其中a是底数,b为指数。从时间复杂度上分析这个算法的复杂度是O(n)级别,咋一看好像好很快,但是往往在比赛、做题的时候都需要处理指数很大运算,例如 10^{10^{6}},即是 10^{1000000},这个时候如果用上面的算法来计算的话,就要循环一百万次,程序就会超时。这个时候快速幂算法就呼之欲出了,先放代码实现:

int __poww(int a,int b){
    int ans = 1;
    while(b){
        if(b & 1 != 0){
            ans *= a;
        }
        a *= a;
        b >>= 1;
    }
    return ans;
}

快速幂算法的原理是通过将指数拆分成几个因数相乘的形式,来简化幂运算。在我们计算 3^{13}的时候,普通的幂运算算法需要计算13次,但是如果我们将它拆分成 3^{8+4+1},再进一步拆分成 3^{8} *3^{4}*3^{1} 只需要计算4次。嗯?哪来的4次?,别急,接着看。

这种拆分思想其实就是借鉴了二进制与十进制转换的算法思想,我们知道13的二进制是1101,可以知道:13= 1*2^{3}+1*2^{2}+0*2^{1}+1*2^{0} = 8+4+1

实现的代码已经给出,原理就是利用位运算里的位移“>>”和按位与“&”运算,代码中 b & 1其实就是取b二进制的最低位,用来判断最低位是0还是1,再根据是0还是1决定乘不乘,不理解的话联系一下二进制转换的过程。b >>= 1其实就是将b的二进制向右移动一位,就这样位移、取最低位、位移、取最低位,这样循环计算,直到指数b为0为止,整个过程和我们手动将二进制转换成十进制是非常相似的。普通幂算法是需要循环指数次,也就是指数是多少就要循环计算多少次,而快速幂因为利用了位移运算,只需要算“指数二进制位的位数”次,对于13来说,二进制是1101,有4位,就只需要计算4次,快速幂算法时间复杂度是O(logn)级别,对于普通幂需要计算一百万次的10^{10^{6}}来说,快速幂只需要计算6次,这是速度上质的飞跃,但是需要多注意溢出的问题。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章