算法分析与模拟枚举

本文介绍了如何运用“空间换时间”原则解决编程问题,特别是针对阿姆斯特朗数(水仙花数)的查找。通过预处理建立表格并在遍历范围内直接调用,避免了暴力枚举导致的时间超限。文章详细阐述了思路和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.算法分析与模拟枚举(2)

阿姆斯特朗数

今天的题型还是枚举,但是这道题让我十分抓狂,当时思考了很长时间,发现如果暴力枚举肯定会时间超限,最后还是在老师的指导下想到了用合理限度内用“空间换时间”的原则解决的。

什么是以空间换时间的原则?

以我的理解之下,时间不够用时,在合适限度内用空间换取更多时间的原则叫做“空间换时间”原则。具体意思是指在时间超限时,用打表或者调用的方式可以节省更多程序的运行时间的方法。它可以让我们的程序运行更快,时间更短,Bug更少等优点,节省更多繁琐的操作。

题目描述

编程找出所有的三位数到七位数中的阿姆斯特朗数。阿姆斯特朗数也叫水仙花数,它的定义如下:若一个n位自然数的各位数字的n次方之和等于它本身,则称这个自然数为阿姆斯特朗数。例如,153(153=1X1X1+3X3X3+5X5X5)是一个三位的阿姆斯特朗数,8208则是一个四位的阿姆斯特朗数。

输出描述

每行输出一个阿姆斯特朗数,按从小到大的顺序按行输出。

如何解决·思路(第一步)

本题的数据范围是百万级别的,如果要算时间复杂度那必定是次方级别增长,所以暴力枚举就首先被程序员否定掉了。那么应该如何解决呢?我们在开始之前应该思考一个问题,应该如何在空间允许的情况下换取更多时间来解决问题。这一点直接关联到刚才提及的“空间换时间”原则。有了这个原则之后应该怎么用呢?我们首先采取打表的方式试试看,在程序开始运行之前做个预处理,方便程序运行的时候可以直接调用,省去了复杂的计算过程。

代码如下
int a[10][10],n[10]; //定义数组a,用来做预处理
for(int i=0;i<=9;i++){ //嵌套for循环可以对二维数组进行遍历
		a[i][1]=i; //将第一行设置为一到九的数字
		for(int j=2;j<=7;j++){ //内层for循环用来设置次方的存储
			a[i][j]=a[i][j-1]*i; //每一个数对应下标存储一到九的一到七次方
		}
}
如何解决·思路(第二步)

做完预处理后,我们应该开始思考如何解决下面的问题了。那就是怎么遍历100到1000000的所有数字了。要说遍历、重复这样的工作肯定少不了for循环的牌面,并且计算机最喜欢做的就是重复干一件事,所以就写一个for循环遍历100到1000000所有整数。再将这个三到七位数依次数位分离在从表格中寻找对应的数进行求值就可以完成此操作。

代码整体理解
#include<iostream> 
using namespace std;
int a[10][10],n[10];
int main(){
	for(int i=0;i<=9;i++){ //预处理操作
		a[i][1]=i;
		for(int j=2;j<=7;j++){
			a[i][j]=a[i][j-1]*i;
		}
	}
	for(int i=100;i<=9999999;i++){ //for循环遍历
		int t=i;
		int nl=0;
		while(t!=0){ //数位分离
			nl++;
			n[nl]=t%10;
			t/=10; 
		}
		int s=0;
		for(int j=1;j<=nl;j++){ //整合统计
			s=s+a[n[j]][nl];
		}
		if(s==i){
			cout<<s<<endl;
		}
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值