·base 继续努力,通过 base *= base 让自己变成了 a^4。然后 b 也右移
一位。b = 10。
·循环三,可是 b 的最后一位不再是 1 了,说明不存在“ × a^4 ”。base 自我升华,达到了 a^8。且 b >>= 1。这一步中,答案没有增加,可是毕竟 b > 0,还有希望。
·循环四,b 的最后一位是 1,这说明“ ×a^8 ”的存在。 ans *= base 。由于 b 再右移一位就是 0 了,循环结束。
总的来说,如果 b 在二进制上的某一位是 1,我们就把答案乘上对应的 a^{2^{n}}。不懂的话,请结合代码理解~
实现
int quickPower(int a, int b)//是求a的b次方
{
int ans = 1, base = a;//ans为答案,base为a^(2^n)
while(b > 0)//b是一个变化的二进制数,如果还没有用完
{
if(b & 1)//&是位运算,b&1表示b在二进制下最后一位是不是1,如果是:
ans *= base;//把ans乘上对应的a^(2^n)
base *= base;//base自乘,由a^(2^n)变成a^(2^(n+1))
b >>= 1;//位运算,b右移一位,如101变成10(把最右边的1移掉了),10010变成1001。现在b在二进制下最后一位是刚刚的倒数第二位。结合上面b & 1食用更佳
}
return ans;
}
原理 II
没错快速幂有很多种理解方式。
这是2017年NOIP普及组的完善程序第1题,这里提示的思路和上面不一样。
从头开始。若当前 p 为偶数,咱们不着急,只需把 x 自乘,然后 p /= 2 (即考虑下一层,下几层会帮我们乘上 (x^2)^{p/2}的)。
若当前 p 为奇数,说明 x^p = x*(x^2)^{(p-1)/2} 中前面那个 x 的存在,ans *= x。然后继续考虑下一层(下几层会帮我们乘上 (x^2)^{(p-1)/2}的)。注意,这里的 x 不是指题目开始给出的 x,而是当前层的 x 应有的值,这跟上面的 base 是一样的。
也是稍稍模拟一下比较好理解。
·假设我们拿到了 x = 3,并且 p = 11。想求 3^{11}。
·第一层循环。b = 11,一个奇数。将 3^{11} 分解为 3^1 * (3^2)^5 来看。本层只需把 ans *= 3^1。那后面的呢?我们到下一层再搞定。下几层的总目标是让 ans *= (3^2)^5,也就是让 ans *= 9^5。*来到下一层的方法是 $x = 33 = 9 且 b = 11 / 2 = 5$。**
·第二层循环几乎独立于第一层存在。b = 5,一个奇数。将 9^{5} 分解为 9^1 * (9^2)^2 来看。本层只需把 ans *= 9^1。那后面的呢?我们到下一层再搞定。下几层的总目标是让 ans *= (9^2)^2,也就是让 ans *= 81^2。于是 x = 9*9 = 81 且 b = 5 / 2 = 2。