快速幂:循环&递归
递归
其实原理很简单,有初一的学历就好,你只需要知道(k为正整数):
- x2k = xk * xk
- x2k+1 = xk * xk * x
- 任何数的0次方都为1(除0外)
- 任何数的1次方都为它本身
至于为什么,问数学老师去
然后一直递归下去即可
代码(计算xk)
int poww(int x , int k){
if(k == 1)
return x;
int tmp = poww(x , k / 2);
if(k % 2 == 0)
return tmp * tmp;
else
return tmp * tmp * x;
}
循环(一般来讲循环会比递归快)
这个稍微有亿一点点复杂
你需要知道:
- 任何数都可以用2的次方(不重复)的和来表示(很简单的道理)10 = 2 + 8 = 21 + 23
15 = 1 + 2 + 4 + 8 = 20 + 21 + 22 +23 - xa1+a2+a3+...+an= xa1 * xa2 * xa3 * ... * xan
不会的问初中数学老师去
那就出来了系不系很简单
再举个栗子:
310 = 32+8 = 32 * 38
把10在二进制下表示是(1010)2(这里想一想位权转换进制10 = 2 + 8 = 21 + 23 )
是不是豁然开朗了
具体实现(1<<i就是2的i次方):
我们把指数k在二进制下一位一位地拆开,拆到第i位时顺便计算x(1<<i) 如果k的(右往左数,从0开始)第i位(注意是二进制)是1,就把x(1<<i)乘到结果里去
代码:
int poww_loop(int x,int k)
{
int res = 1;
while(k)
{
if(k&1 == 1)
res *= x;
x *= x;//注意现在的x已经不是原来的底数,而是原来的底数的(2的i次方)的次方
k >>= 1;
}
return res;
}
附:位运算
不详细讲,自己写代码试试,或者到网上搜
移位(">>" & "<<")
把二进制表示下把数字同时向左(右)移动,越界部分舍去,新增部分补0
n << p = n * 2p
n >>p = n / 2p
10 << 1 = 20
与运算(&)
如果n&1 == 1,则n是奇数,否则n是偶数
if(n & 1 == 0)等价于 if(n % 2 == 0),但是位运算的效率会更高