# 王道机试练习——巧妙求A^B(A的B次幂)二分求幂法

王道机试练习——巧妙求A^B(A的B次幂)二分求幂法

题目描述

求 A^B 的最后三位数表示的整数。说明: A^B 的含义是 ―A的 B 次方
输入: 输入数据包含多个测试实例,每个实例占一行,由两个正整数 A 和 B 组成 (1<=A,B<=10000),如果 A=0, B=0,则表示输入数据的结束,不做处理。
输出: 对于每个测试实例,请输出 A^B 的最后三位表示的整数,每个输出占一行。
样例输入:
23
12 6
6789 10000
00
样例输出:
8
984
1

二分求幂法

我们的目标即分解 a 的 b 次变为若干个 a 的 2^k 次
的积,并尽可能减少分解结果的个数。在指数层面即分解 b 为若干个 2^k 的和, 并尽可能减少分解结果的个数。若读者认真完成了本章之前的内容,就应该能联 想到分解 b 为若干个 2^k 的和且分解个数最小,这便是求 b 的二进制数。在求得 b 的二进制数后,各个二进制位为 1 的数位所代表的权重即是分解的结果。以 2 的 31 次方为例,我们首先求得 31 的二进制数 11111,在二进制表达式中 31 即被 表达成 (11111) = 2^0 + 2^1 + 2^2 + 2^3 + 2^4,这就是我们所需的分解结果。即拆 2 的 31 次为 2 的 0 次、1 次、2 次、3 次、4 次的乘积,即得到前文中所讲的结 果。 所以,二分求幂对要求的次数并没有特殊的要求,而是对任何要求的次数都 可以采用二分求幂来大大减少其乘法运算的次数。

解题原理

那么在本例中,我们先求得 A^B 的具体数字再求其后 三位数么?这毫无疑问是不可行的,按照题面给明的输入规模, A^B 的次至多 可以达到 10000 的 10000 次,这么庞大的数字是非常不容易保存的,但是我们应
该注意到 A^B 的后三位数只与 A 的后三位数和 B 有关。这样,由于要求的仅是 最后结果的后三位数,那么我们在保存为计算该最终值的中间值时也只需保存其 后三位数即可。即,计算过程中的所有中间结果我们仅保存和使用其后三位数。 那么,我们再利用二分求幂来求得 A^B 次,同时在计算中间结果时我们都仅保 存后三位数。这样 ,我们就不用担心数字不能被保存的问题了 。

代码

#include<iostream>
using namespace std;
int main() {
	int a, b;
	while (cin >> a >> b) {
		if (a == 0 && b == 0) break;
		int ans = 1;//保存最终变量,初始值为1
		while (b != 0) {//若b不等于0,即对b转换2进制过程未结束
			if (b % 2 == 1) {//若当前二进制位为1,则需要累成a的2^k次至变量ans
				//其中2^k为当前二进制位的权重
				ans *= a;//最终结果累乘a
				ans %= 1000;//求其后三位数
			}
			b /= 2;//b除以2
			a *= a;//求下一位二进制位的权重,a求其平方,即从a的1次开始,依次求a的2次,a的4次……
			a %= 1000;//求a的后三位
		}//一边计算b的二进制,一边计算a的2^k次,并将需要的部分乘到变量ans上
		cout << ans;//输出
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值