作者 徐镜春 单位 浙江大学
水仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身。例如:153=13+53+33。 本题要求编写程序,计算所有N位水仙花数。
输入格式:
输入在一行中给出一个正整数N(3≤N≤7)。
输出格式:
按递增顺序输出所有N位水仙花数,每个数字占一行。
输入样例:
3
输出样例:
153
370
371
407
1. 主要思路:
主函数:输入N,遍历所有N位数,同时判断是否为水仙花数,是则输出,否则继续判断下一个。
find(int n,int N):功能为判断是否为水仙花数。实现:使用while循环,每次都获取n%10的值temp;再求temp的N次方,然后加到sum;最后让n除以10;直到n等于0就跳出循环。最后判断sum是否等于n,如果相等即n为水仙花数。
2. 代码
优化前代码:
#include<stdio.h>
#include <math.h>
int find(int n,int N){
int a=n;
int sum=0;
int temp;
while(n==0){
temp=(n%10);
sum+=pow(temp,N);
n=n/10;
}
if(sum==a){
return 1;
}else{
return 0;
}
}
int main(){
int N;
scanf("%d",&N);
int i=pow(10,N-1);
int max=pow(10,N);
for(i;i<max;i++){
if(find(i,N)==1){
printf("%d\n",i);
}
}
return 0;
}
问题:运行超时
分析:找代码中哪些地方可能会需要比较长的时间,发现两处。第一处是一次判断是否为水仙花数的for循环,但是发现必不可少不能简化。第二处是pow函数,发现pow(x,y)中,x、y及函数值都是double型,运行时间相对较长;同时pow是函数,传递参数,调用函数的代价远大于直接相乘。所有从第二处下手,将使用pow函数的地方都改为for循环,再运行测试就没有超时了。
优化后代码:
#include<stdio.h>
#include <math.h>
int find(int n,int N){
int a=n;
int sum=0;
int temp,t;
while(n!=0){
temp=(n%10);
t=temp;
for(int j=1;j<N;j++){
t*=temp;
}
sum+=t;
n=n/10;
}
if(sum==a){
return 1;
}else{
return 0;
}
}
int main(){
int N;
scanf("%d",&N);
int i=1;
for(int j=0;j<N-1;j++){
i*=10;
}
int max=1;
for(int j=0;j<N;j++){
max*=10;
}
for(i;i<max;i++){
if(find(i,N)==1){
printf("%d\n",i);
}
}
return 0;
}