【C语言基础】->自幂数优化->这个算法快得像一道闪电

Ⅰ 自幂数的定义

自幂数是指一个 n 位数,它的每个位上的数字的 n 次幂之和等于它本身。(例如:当n为3时,有1^3 + 5^3 + 3^3 = 153,153即是n为3时的一个自幂数)

自幂数包括:独身数、水仙花数、四叶玫瑰数、五角星数、六合数、北斗七星数、八仙数、九九重阳数、十全十美数

n为1时,自幂数称为独身数。显然,0,1,2,3,4,5,6,7,8,9都是自幂数。
n为2时,没有自幂数。
n为3时,自幂数称为水仙花数,有4个:153,370,371,407;
n为4时,自幂数称为四叶玫瑰数,共有3个:1634,8208,9474;
n为5时,自幂数称为五角星数,共有3个:54748,92727,93084;
n为6时,自幂数称为六合数, 只有1个:548834;
n为7时,自幂数称为北斗七星数, 共有4个:1741725,4210818,9800817,9926315;
n为8时,自幂数称为八仙数, 共有3个:24678050,24678051,88593477;
n为9时,自幂数称为九九重阳数,共有4个:146511208,472335975,534494836,912985153;
n为10时,自幂数称为十全十美数,只有1个:4679307774。

Ⅱ 需求分析

该程序的目的是输出一定范围内的所有自幂数,要判断一个数是不是自幂数,我们需要得到它的位数,然后根据每位的位数次方之和来判断该数是不是自幂数。
得到位数以及次方和,便是这个程序的主要步骤,因此,优化该程序也应从这两部的效率最高的方法考虑。

在我的哥德巴赫猜想验证的博客中,我给出了一个代码从最初级到极限的算法优化全部步骤,感兴趣的同学可以移步去看那篇文章,在此我不再赘述,直接考虑自幂数算法的极限情况。

【C语言】->哥德巴赫猜想验证->筛选法->算法极限优化之你不可能比我快

Ⅲ 算法优化

a. 得到当前数字的位数

关于这一步,惯常的想法是通过不断 /10 得到位数,事实上最快的做法是用 if 条件语句直接判断。由于int类型最大数是42亿左右,十全十美数已经超过了这个范围,所以我们只考虑十位以下的数。

int getBits(int number) {
   
	if (number >= 100000000 && number < 1000000000) {
   
		return 9;
	}
	if (number >= 10000000 && number < 100000000) {
   
		return 8;
	}
	if (number >= 1000000 && number < 10000000) {
   
		return 7;
	}
	if (number >= 100000 && number < 1000000) {
   
		return 6;
	}
	if (number >= 10000 && number < 100000) {
   
		return 5;
	}
	if (number >= 1000 && number < 10000) {
   
		return 4;
	}
	if (number >= 100 && number < 1000) {
   
		return 3;
	}
	if (number >= 10 && number < 100) {
   
		return 2;
	}
	if (number >= 0 && number < 10) {
   
		return 1;
	}
}

这里还有个需要注意的地方,就是要从最大位数开始判断,因为往后数字越大最后判断自幂数的时间就越长,所以把最大的数放在靠上面的语句,这样可以更快的得到更大数的位数,即使只是省了几行语句的时间。

b. 判断自幂数

要知道一个数是不是自幂数,我们需要将每一位的数字的位数次方加起来,然后和本身做比较。这就牵扯到每次判断可能都要调用pow()函数,但是这样是很花时间的。

在做哥德巴赫猜想验证时,我们先生成了一个质数池,每次判断一个数是不是质数,直接在质数池中取就知道了。同样的思路,我们判断自幂数时,不用当场算它的幂级数,而是直接取。这就用到了二维数组。

因为每个数字的每一位上只可能是0 到 9 这十个数字,且数字的位数也是0 到 9位,所以其幂指数也是只可能是 0 到 9 这十个数字。所以我们先算完,然后存入二维数组中,到时候直接调取就好了。

const int array[10][10] = {
   
/*0*/	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/*1*/	0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
/*2*/	0, 1, 4, 9, 16, 25, 36, 49, 64, 81,
/*3*/	0, 1, 8, 27, 16*4, 125, 36*6, 49*7, 64*8, 81*9,
/*4*/	0, 1, 16, 81, 16*4*4, 125*5, 36*6*6, 49*7*7, 64*8*8, 81
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值