一个引子
如何求得a的b次幂呢,那还不简单,一个for循环就可以实现!
void main(void) { int a, b; int ans = 1; cin >> a >> b; for (int i = 1; i <= b; i++) { ans *= a; } cout << ans; }
那么如何快速的求得a的b次幂呢?上面的代码还可以优化吗?
当然是ok的!下面就介绍一种方法-二分求幂。
二分求幂
所谓二分求幂,即是将b次幂用二进制表示,当二进制位k位为1时,需要累乘a的2^k次方。
下面优化一下上面的代码:
void main(void) { int a, b; int ans = 1; cin >> a >> b; while (b != 0) { //当二进制位k位为1时,需要累乘a的2^k次方,然后用ans保存 if (b % 2 == 1) { ans *= a; } a *= a; //每次除以2,转换成二进制位 b /= 2; } cout << ans; }
举个例子,当b = 5时,b的二进制为101。
循环次数 | 二进制位 | ans值 | a值 | b值 |
0 | 101 | 1 | a | 5 |
1 | 101 | 2 | a2 | 2 |
2 | 101 | 2 | a4 | 1 |
3 | 101 | 32 | a16 | 0 |
从上表我们可以直观的看出5次幂就可以转换为(2^0+2^2),即a的5次幂就转变为a的(2^0+2^2)次幂,即a的2^0与a的2^2的乘积。
再来个例子-巩固
此题来源于九度教程“人见人爱A^B”。
题目描述:
求A^B的最后三位数表示的整数。
输入:
输入数据包含多个测试实例,每个实例占一行,由两个正整数a和b组成,其中(1<=a,b<=10000),如果a = 0,被= 0,则表示输入数据结束,不做处理。
输出:
对于每个测试实例,输出a^b的最后三位表示的整数,每个输出占一行。
样例输入:
2 3
12 6
6789 10000
0 0
样例输出:
8
984
1
对于这道题,完全可以用上面的二分求解方法,可以仿照上面的代码进行实现。但是有一点需要注意的是,我们不肯能定义一个整型变量或者long long类型的变量取保存如样例给出的数据a = 6789,b=10000,a^b的计算结果。因为数字太庞大了,在整数范围内是无法表示的。所以我们可以只保存每次计算结果的后三位,因为最终结果的后三位取决于其中间值的后三位。
好吧,给出代码:
void main(void) { int a, b; while ((cin >> a >> b)) { int ans = 1; if (a == 0 && b == 0) break; while (b != 0) { //当二进制位k位为1时,就累加a的2^k次方 if (b % 2 == 1) { ans *= a; ans %= 1000; } a *= a; a %= 1000; //每次除以2,转换成二进制位 b /= 2; } cout << ans; } }