快速幂算法 ——递归与迭代
快速幂算法讲解
递归算法:
int cpow(int m,int n) { if(n==0) return 1; else if(n%2==1){ return cpow(m,n-1)*m; }else if(n%2==0) { int temp = cpow(m,n/2); return temp*temp; } }
例如:当我们已知了 2^3,那么在计算2^6不就是相当于2^3*2^3,而快速幂就是运用了这样的原理,但是,如果我们碰到的幂为奇数时怎么办?直接提出来一个幂不就好了,例如在计算2^7,将此转换成2*2^6,之后2^6继续运用上面对待偶数的办法不就好了;
总结以上啰里啰嗦的话,转换成公式就是一下:
1)当b是奇数时,那么有 a^b = a * a^*(b-1)
2)当b是偶数时,那么有 a^b = a^(b/2) * a^(b/2)
迭代算法:
int qpow(int a,int n) { int nas = 1; while(n){ if(n&1) ans *= a; a *= a; n>>=1; } return ans; }
迭代算法运用到了位运算&,将递归算法的(n%2==0)改为(n&1);
对于 a ^ b来说,若果把 b 写成2 进制,那么b 就可以写成若干二次幂之和,如13 的二进制 1101,于是3 号位 、2号位、0号位就都是1,那么就可以得到13 = 2^3 + 2^2 + 2^1 = 8 + 4 + 1。所以a ^13 = a^8 * a^4 * a^1。
通过同样的推导,我们可以把任意的a^b 表示成 a^(2^k)……、a^8、a^4、a^2、a^1中若干的乘积。若果二进制的i号位为1.那么想中的a^(2^i)就被选中。于是可以得到计算a^b的大致思路:令i 从0到k枚举b的二进制的每一位,如果为1 那就累计a^(2^i)。注意
a^(2^k)……、a^8、a^4、a^2、a^1前一项总是等于后一项的平方。具体步骤。
(1)初始令ans = 1,用来存放累积的结果。
(2)判断b的二进制末尾是否为1 ,(及判断 b&1 是否为 1),也可以理解为判断b 是否为奇数。如果是的话,令ans乘上a的值。
(3)令a平方,并使b右移一位,(也可以理解为,b/2)
(4)只要b 大于0,就返回(2)。
以上;