题目内容
- 写两个函数
- 函数narcissistic,传入一个值,用于判断输入的数是不是水仙花数,是水仙花数返回1,否则返回0
- 函数PrintN,传入两个值,求开区间范围内所有水仙花数
注1:题目中保证100≤m≤n≤10000
注2: 水仙花数:一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身
eg: 153 = 1 * 1 * 1 + 5 * 5 * 5 + 3 * 3 * 3
测试程序样例
#include <stdio.h>
int narcissistic( int number );
void PrintN( int m, int n );
int main()
{
int m, n;
scanf("%d %d", &m, &n);
if ( narcissistic(m) ) printf("%d is a narcissistic number\n", m);
PrintN(m, n);
if ( narcissistic(n) ) printf("%d is a narcissistic number\n", n);
return 0;
}
在程序后面完成自己的函数
输入样例
153 400
输出样例
153 is a narcissistic number
370
371
注 题目来源:浙大版《C语言程序设计(第3版)》题目集
解题思路
观察题目,输入和输出样例,可知printN函数的两端是开区间,会帮我们判断两端是否是水仙花数,且数字后有"is a narcissistic number",我们的函数只需输出数字
再观察程序头部和主函数,printN函数的类型是void,主函数中也没有关于printN的输出语句,因此我们的printN函数不需要return,而是在函数中直接输出
我们可以通过在printN函数中调用narcissistic函数,将所有结果是1的数进行输出来完成寻找水仙花数
而narcissistic函数需要我们把一个三位数或者四位数的每一位拆开进行,进行幂运算,判断这个数是不是水仙花数,而要把每一个数拆开,我们要先判断这个数是几位数
柿子挑软的捏(doge),所以咱可以先写printN函数
void PrintN( int m, int n )
{
int i;
for(i=m+1;i<n;i++)
{
if ( narcissistic( i ) ) {
printf("%d\n", i);
}
}
}
只需要一个for循环和一个嵌套着narcissistic函数的if语句就可以搞定
因为调用了narcissistic函数,所以我们的narcissistic函数要放在printN函数的上面,按照刚才的思路,我们先判断数字是几位数,然后按照不同的位数分类讨论取出每一位数,之后进行判断输出。好在题目中给了我们m和n的范围,最大是10000,用脚趾算一下就可以知道这不是水仙花数,所以我们只需要判断这个数是三位数或者四位数就可以了
需要注意的是在头文件中我们没有调用math.h库,所以函数里不能使用pow()函数
int narcissistic( int number)
{
int i = 1,result = 0;
int number1 = number;
//这里用到number1的原因是下面while循环做位数判断的时候
//要一个number进行自除,之后还需要一个number进行判断
int a = 0, b = 0, c = 0, d = 0;
while (number1 >= 10 ) {
number1 /= 10;
i += 1;
}
//上面用于判断一个数字有几位数
if (i == 3) {
a = number % 10;
b = number / 10 % 10;
c = number / 100;
if (number == a*a*a+b*b*b+c*c*c) {
result = 1;
}
}
if (i == 4) {
a = number % 10;
b = number / 10 % 10;
c = number / 100 % 10;
d = number / 1000;
if (number == a*a*a*a+b*b*b*b+c*c*c*c+d*d*d*d) {
result = 1;
}
}
return result;
}
看一下结果
输入:
153 400
输出:
153 is a narcissistic number
370
371
没有问题!!!
方法优化
今天早上起来又看到这道题,仔细一想,这段代码(特别是narcissistic函数)有很多可以优化的地方,比如虽然头文件中没有给出<math.h>库,但我i们可以尝试在函数的上面自己加入<math.h>库
#include <math.h>
int narcissistic( int number)
像这样
还有就是在判断一个数字是几位数的时候,完全没必要像我一开始那样小题大做,用一个while循环来判断这个数字是几位数,极大的提升了这道题的时间复杂度,因为题目保证了最大数字是10000,最小的水仙花数也是三位数,所以我们只要用两个if语句就可以把三位数和四位数分别处理,修改后代码如下:
#include <stdio.h>
int narcissistic( int number );
void PrintN( int m, int n );
int main()
{
int m, n;
scanf("%d %d", &m, &n);
if ( narcissistic(m) ) printf("%d is a narcissistic number\n", m);
PrintN(m, n);
if ( narcissistic(n) ) printf("%d is a narcissistic number\n", n);
return 0;
}
#include <math.h>
int narcissistic( int number)
{
int i = 1,result = 0;
int a = 0, b = 0, c = 0, d = 0;
if (number>=100 && number < 1000) {
a = number % 10;
b = number / 10 % 10;
c = number / 100;
if (number==pow(a,3)+pow(b,3)+pow(c,3)) {
result = 1;
}
}
if (number>=1000 && number < 10000) {
a = number % 10;
b = number / 10 % 10;
c = number / 100 % 10;
d = number / 1000;
if (number==pow(a,4)+pow(b,4)+pow(c,4)) {
result = 1;
}
}
return result;
}
void PrintN( int m, int n )
{
int i;
for(i=m+1;i<n;i++)
{
if ( narcissistic( i ) ) {
printf("%d\n", i);
}
}
}
narcissistic函数比之前少了近10行代码!!
总结
收获的知识:
调用的库不一定要卸写在文件的最上面,写在函数的最上面也能正常运行
在数字范围差别不大的情况下,用if语句代替while循环效率会更高
希望能帮到大家!!