快速幂:循环&递归

递归

其实原理很简单,有初一的学历就好,你只需要知道(k为正整数):

  1. x2k = xk * xk
  2. x2k+1 = xk * xk * x
  3. 任何数的0次方都为1(除0外)
  4. 任何数的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;
}

循环(一般来讲循环会比递归快)

这个稍微有亿一点点复杂
你需要知道:

  1. 任何数都可以用2的次方(不重复)的和来表示(很简单的道理)在这里插入图片描述10 = 2 + 8 = 21 + 23
    15 = 1 + 2 + 4 + 8 = 20 + 21 + 22 +23
  2. 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),但是位运算的效率会更高

posted @ 2020-11-11 10:45  追梦人1024  阅读(137)  评论(0编辑  收藏  举报