水仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身。例如:$153=1^3+5^3+3^3$。 本题要求编写程序,计算所有N位水仙花数。

输入格式:

输入在一行中给出一个正整数N(3≤N≤7)。

输出格式:

按递增顺序输出所有N位水仙花数,每个数字占一行。

输入样例:

3

输出样例:

153
370
371
407
#include <stdio.h>
#include <math.h>
int sumDaffodil(int,int*);
int main(int argc, const char *argv[])
{
    int n,i,j,k;
    scanf("%d",&n);
    int start,end;
    int arr[7] = {0};
    if(n>=3 && n<=7)
    {
        start = pow(10,n-1);
        end = pow(10,n);
        for(i=start;i<end;i++)
        {
            k=i;
            for(j=n-1;j>=0;j--)
            {
                arr[j] = k%10;
                k /= 10;
            }
            if(i == sumDaffodil(n,arr))
                printf("%d\n",i);
        }
    }
    return 0;
}
int sumDaffodil(int n,int* arr)
{
    int i,j,sum = 0,mul = 1;
    for(i=0;i<n;i++)
    {
        mul = 1;
        for(j=0;j<n;j++)
        {
            mul *= arr[i];
        }
        sum += mul;
        //sum += pow(num%10,n);
        //num /= 10;
    }
    return sum;
}

总结

本题的思路其实比较清晰:首先要有一个大循环来遍历n位正整数,在遍历过程中对每一个正整数进行拆分求各位数的n次幂和。求幂可以调用函数pow(),但如果对所以求幂都都要pow(),会发现当n过大时调用pow()的次数会非常大,结果是耗时长无法通过测试。

解决方法是:一是将循环的范围拎到for()之前单独计算start和end。二是改用数组先保存当前遍历的正整数的各位数,在sumDaffodil函数中改用for循环对数组中每一位进行n次自乘来取代pow()。

最后耗时342ms,测试时间限制是2500ms,可见pow()函数调用多了是多么耗时。(假设n=7,那么原先在for(i=pow(10,n-1);i<pow(10,n);i++))中要调用9000000次,在这个for循环中每次都要调用sumDaffodil函数,该函数中有一个for(i=0;i<n;i++)循环,每次循环要调用一次sum += pow(num%10,n);,即函数中要调用7次,那么一共需要调用7*9000000=6300 0000次的pow()函数。)

Last modification:2021 年 03 月 27 日 16 : 10 : 02