[C]证明X的62次方可以只用8次乘法算出

近日看到一道算法题:
题目
这个题目引起了我的兴趣,
于是我着手开始设计算法,以下便是我想到并琢磨改良出的第一个解法:

//used用来累计使用乘法的次数
#include <stdio.h>
#include <stdlib.h>
#define NUMBER 2
#define P 62
int used = 0;
//62=32+16+8+4+2
long long p(long long x, int in) {
	long long number = 1;
	do {
		if (in & 1) {
			number *= x;
			++used;
		}
	} while ((in >>= 1) && ((x *= x), (++used), 1));
	//这里while内的乘法也被计入
	return number;
}
int main() {
	printf("%d的%d次方的值:%lld\n", NUMBER, P, p(NUMBER, P));
	printf("计算%d的%d次方的乘法使用次数:%d\n", NUMBER, P, used);
}

算法很简短,计算速度很快,也不占用空间,主要依靠幂的最右边的二进制位是否为1来判断是否相乘从而使幂相加(同底数幂相乘,底数不变,指数相加),使得幂最终达到62,算出N^62次方的值。

Tip:(x *= x)之所以不写在循环体内,是因为这样可以减少掉最后使那一次无意义的乘法
结果

通过计算器可知结果是对的,可是步骤仍然太多,需要足足10步…
验证
于是我开始寻思更好的改良方法,但可惜我觉得这个算法已经是最优了

所以我开始搜索,看看网上有没有关于这个问题的解法

于是我看到这个时(https://bbs.csdn.net/topics/190051933)

我有了一丝灵感。
查找中
迅速的,我经过一些试错和思考,决定特化算法,写出一个针对X^62次方的算法

最终成果如下:

//used用来累计使用乘法的次数
#include <stdio.h>
#include <stdlib.h>
#define NUMBER 2
#define P 62
int used = 0;
//62=32+16+8+4+2
long long p(long long x, int in) {
	long long number = x;
	int in_save = in;//保存in值
	int num = 1;//上限值的幂
	do{
			number *= number;
			++used;
			num <<= 1;
	}while ((in >>= 1));
	//此时number是上限值,在这里number是2^64次方
	//该值太大,使得在这里时,number成了0,但因为算法不依靠number的值,所以无影响
	num -= in_save;
	//64-62得出2,这意味着我需要把number除以2^2就能得出2^62的值
	do {
		if (num & 1) {
			number /= x;
			//除以x可看做是乘以x的倒数,所以这里除法,我看做为乘法
			++used;
		}
	} while ((num >>= 1) && ((x *= x), (++used), 1));
	//这里while内的乘法也被计入
	return number;
}
int main() {
	printf("%d的%d次方的值:%lld\n", NUMBER, P, p(NUMBER, P));
	printf("计算%d的%d次方的乘法使用次数:%d\n", NUMBER, P, used);
}

8步!我解掉了!
运行图:
运行图
恩?你问这个2^62的计算结果不对?这其实只是计算出的值过大导致的数值错误,但我这里的算法是以幂为依据做循环和计算的,所以结果不影响。
如果你还不相信,我们可以看看2^31次方结果如何,来看看这个算法是否正确!
结果
可以看出,我的算法没有问题,这就是能正确以8步来计算X^62次方的算法!且无论X初始是多少。
结果
结果

好,此题已解,谢谢观看,如有错误,欢迎指出。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值