`
universsky
  • 浏览: 99508 次
文章分类
社区版块
存档分类
最新评论

求解10位数以内的水仙花数:普通的穷举算法 另:优化的深度优先搜索算法。

 
阅读更多
/*
水仙花数是指一个 n 位数 ( n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身。
(例如:1^3 + 5^3 + 3^3 = 153)
普通的穷举算法,
CPU0: Intel(R) Pentium(R)
CPU P6200  @ 2.13GHz
求解8位数以内的水仙花数需要45s左右的时间,

*/

/**
@author : 东海陈光剑 2013.4.26 Friday ,01:02

*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//#include <math.h>

/* 求1-N 以内的水仙花数 */
#define N 1e8
//typedef enum {true = 0, false = !true} bool;

/**
打印日志时间
*/
void print_time()
{
    time_t my_time; // time_t
/*
    时间类型(time.h 定义)
struct tm -- 时间结构,time.h 定义如下:
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;

*/
    struct tm* timeinfo;
    time( &my_time );//获取时间,以秒计,从1970年1月一日起算,存于my_time
    timeinfo = localtime( &my_time );//转为当地时间,tm 时间结构
    //printf ( "\007The current date is: %s", asctime (timeinfo) );
/*asctime()-- 转为标准ASCII时间格式:星期 月 日 时:分:秒 年*/

    printf ( "[%4d-%02d-%02d %02d:%02d:%02d]",
            1900+timeinfo->tm_year,
            1+timeinfo->tm_mon,
            timeinfo->tm_mday,
            timeinfo->tm_hour,
            timeinfo->tm_min,
            timeinfo->tm_sec);
/*
打印tm,tm_year 从1900年计算,所以要加1900,
月tm_mon,从0计算,所以要加1 */

}


/**
取数字位数
*/
int get_power_index(int n)
{

    int power_index = 0;
    while (n > 0)
    {
        power_index ++;
        n /= 10;
    }

    return power_index;
}

/**计算数字各位上数字的k次方(k=数字的位数)*/

int my_pow(int* a, int* b)
{
    int i=0;
    int p=1;
    //int pow = 1;
    for (i = 0; i < *b; i++)
    {
      p *= *a;
    }

    return p;
}

/**判断x是否是水仙花数*/
int is_flower(int x)
{
    int sum = 0;
    int a = 0;
    //int* pindex =NULL;
    int pindex = get_power_index( x );
   // int bits = power_index;
    int n=x;

    while (n > 0)
    {
        a = n % 10;
        sum += my_pow( & a , & pindex);
        n = (( n - n % 10 )/10);// n去尾
    }


    if (x == sum )
    {
       // printf(" %d 位数: ",*pindex);
        return 0;
    }
    else
    {
        return 1;
    }
}



int main()
{
    // test
    print_time();
    printf("Testing....\nThe result is 9,625,010001000\n");
    //printf("%c\n",ctime(gmtime()));
    int a=5;
    int b=4;
    printf("%d\n",get_power_index(124667459));// 9
    printf("%d\n",my_pow(&a,&b));// 625

    printf("%d\n",is_flower(153));//0
    printf("%d\n",is_flower(875));//1
    printf("%d\n",is_flower(370));//0
    printf("%d\n",is_flower(371));//0
    printf("%d\n",is_flower(407));//0
    printf("%d\n",is_flower(934));//1
    printf("%d\n",is_flower(93084));//0
    printf("%d\n",is_flower(92727));//0
    printf("%d\n",is_flower(54748));//0


    print_time();
    printf("求1- %lf 以内的水仙花数.....\n",N);


    int i;

    clock_t start, finish;
    double duration;

    //printf("%c\n",ctime(gmtime()));

    start = clock(); // 计时开始

    // 穷举算法
    for(i=1;i<N;i++)
    {
        if(is_flower(i) == 0)
        {
            printf("%d位数的水仙花:%d\n",get_power_index(i),i);
        }
    }

    print_time();

    finish = clock(); //计时结束

    //printf("%c\n",ctime(gmtime()));

       /* 测量一个事件持续的时间*/
    duration = (double)(finish - start) / CLOCKS_PER_SEC;
    printf( "Time using is %f seconds\n", duration );
      //system("pause");

    return 0;
}



/*
#include <stdio.h>
#include <time.h>

void main ()
{
time_t rawtime;
struct tm * timeinfo;

time ( &rawtime );
timeinfo = localtime ( &rawtime );
printf ( "\007The current date/time is: %s", asctime (timeinfo) );

exit(0);
}

=================
#include <time.h> -- 必须的时间函数头文件
time_t -- 时间类型(time.h 定义)
struct tm -- 时间结构,time.h 定义如下:
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;

time ( &rawtime ); -- 获取时间,以秒计,从1970年1月一日起算,存于rawtime
localtime ( &rawtime ); -- 转为当地时间,tm 时间结构
asctime ()-- 转为标准ASCII时间格式:
星期 月 日 时:分:秒 年
=========================================
你要的格式可这样输出:
printf ( "%4d-%02d-%02d %02d:%02d:%02d\n",1900+timeinfo->tm_year, 1+timeinfo->tm_mon,
timeinfo->tm_mday,timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);

就是直接打印tm,tm_year 从1900年计算,所以要加1900,
月tm_mon,从0计算,所以要加1
其它你一目了然啦。
*/



/*
#include<math.h>

函数原型是:
1.double pow(double _X,double _Y);
2.double pow(double _X,int _Y);
3.long double pow(long double _X,long double _Y);
4.long double pow(long double _X,int _Y);
5.float pow(float _X,float _Y);
6.float pow(float _X,int _Y);

原型:extern float pow(float x, float y);

用法:#include

功能:计算x的y次幂。

说明:x应大于零,返回幂指数的结果。

举例:

// pow.c

#include
#include
#include
void main()
{
printf("4^5=%f",pow(4.,5.));
getchar();
}
#include
#include

void main( void )
{
double x = 2.0, y = 3.0, z;

z = pow( x, y );
printf( "%.1f to the power of %.1f is %.1f ", x, y, z );
}


Output

2.0 to the power of 3.0 is 8.0


*/



/*
整型 [signed]int -2147483648~+2147483648
无符号整型unsigned[int] 0~4294967295
短整型 short [int] -32768~32768
无符号短整型unsigned short[int] 0~65535
长整型 Long int -2147483648~+2147483648
无符号长整型unsigned [int] 0~4294967295
字符型[signed] char -128~+127
无符号字符型 unsigned char 0~255
单精度 float 3.4 x 10^(-38)~ 3.4 x 10^(+38)
双精度double 1.7 x 10^(-308)~ 1.7 x 10^(+308)
长双精度 long double 1.7 x 10^(-308)~ 1.7 x 10^(+308)
*/

/*
time() 取得本地时间(日期时间函数)
settimeofday() 设置当前时间戳
mktime() 将时间结构数据转换成经过的秒数
localtime() 获取当地目前时间和日期
gmtime() 获取当前时间和日期
gettimeofday() 获取当前时间
ctime() 将时间日期以字符串格式表示
asctime() 将时间日期以字符串格式表示

printf("%s\n",ctime(gmtime()));





*/



/*
常见水仙花数
水仙花数又称阿姆斯特朗数。
水仙花数

水仙花数
三位的水仙花数共有4个:153,370,371,407;四位的水仙花数共有3个:1634,8208,9474;
五位的水仙花数共有3个:54748,92727,93084;
六位的水仙花数只有1个:548834;
七位的水仙花数共有4个:1741725,4210818,9800817,9926315;
八位的水仙花数共有3个:24678050,24678051,88593477
……
……
使用高精度计算,可以得到超过INT类型上限的水仙花数:
5: 93084
5: 92727
5: 54748
6: 548834
7: 9800817
7: 4210818
7: 1741725
7: 9926315
8: 24678050
8: 24678051
8: 88593477
9: 146511208
9: 912985153
9: 472335975
9: 534494836
10: 4679307774
11: 32164049650
11: 40028394225
11: 42678290603
11: 49388550606
11: 32164049651
11: 94204591914
11: 44708635679
11: 82693916578
14: 28116440335967
16: 4338281769391370
16: 4338281769391371
17: 35875699062250035
17: 21897142587612075
19: 3289582984443187032
19: 4929273885928088826
19: 4498128791164624869
20: 63105425988599693916
21: 449177399146038697307
21: 128468643043731391252
23: 27907865009977052567814
23: 35452590104031691935943
23: 27879694893054074471405
23: 21887696841122916288858
24: 174088005938065293023722
24: 188451485447897896036875
(为环保起见,24位以上的水仙花数略)
理论上,最大的水仙花数不超过34位。
*/

分享到:
评论

相关推荐

    江苏省二级C语言上机考试常见算法

    在100至1000之间查找水仙花数,可以通过遍历所有三位数并检查每个数是否满足上述条件实现。 #### 4. 排序算法 **冒泡排序**是最基础的排序算法之一,其基本思想是通过不断比较相邻元素并交换位置,使较大的元素...

    信息技术竞赛培训教程_算法和数据结构综合应用

    3. **数值计算问题**:包括寻找特定数值属性的数,如“水仙花数”(三位数,其各位数字立方和等于该数字本身)和“完数”(因子之和等于自身的数)。 4. **递推与迭代法**:递推是通过已知的当前状态推导出下一状态...

    c语言常用算法

    // 检查一个数是否是水仙花数 int num = 153; // 假设我们要检查的数是153 int sum = 0, temp = num; while (temp != 0) { int digit = temp % 10; // 获取个位数 sum += digit * digit * digit; // 累加每个位的...

    java算法题目.pdf

    3. **水仙花数**:程序3中的水仙花数是三位数,满足各位数立方和等于自身,可以用三重循环来实现,分别处理百位、十位和个位。 4. **质因数分解**:程序4是质因数分解,通过不断找到最小的质数k来分解n,直到n=1。 ...

    专升本C++复习题.docx

    5. "水仙花数"的输出:对于n位的水仙花数,需要计算每位数字的n次方和,判断是否等于原始数字。 6. 回文数的寻找:定义一个函数`bool huiwen(int n)`,检查数字是否为回文,然后在指定范围内查找满足条件的数。 7....

    C++题集.pdf

    26. 水仙花数:遍历100到999之间的数,判断其各位数的立方和是否等于其本身。 以上是基于题目内容解析的C++编程相关知识点,涵盖了数据类型、逻辑控制、数学运算等多个方面,适合初学者和进阶者练习。

    c语言试题100道.docx

    25. 水仙花数:检查三位数的每一位立方和是否等于自身。 26. 鸡兔同笼问题:建立线性方程组求解。 27. 钱币兑换:使用回溯法或穷举法找出所有组合。 28. 三色球问题:组合数学的应用,计算组合数。 29. 平方根表:...

    C语言计算机二级等考算法总结

    - **水仙花数**:是指一个n位数(n≥3),它的每个位上的数字的n次幂之和等于它本身。 - **最大公约数、最小公倍数**:可以使用辗转相除法(欧几里得算法)来计算两个数的最大公约数,并进一步计算最小公倍数。 ###...

    输入两个正整数m和n求其最大公约数和最小公倍数 (2).docx

    数列操作:遍历特定范围的数,检查是否满足特定条件(如水仙花数),并进行输出。 17-24. 矩阵操作:处理二维数组,计算对角线元素之和、平均值、最大值,同时保持原矩阵的完整性。 25. 对称矩阵检测:比较矩阵的...

    c++编程练习题1(适合广大新手学习)

    14. 水仙花数:理解三维数的定义,计算每个位数的立方和。 15. 完数:检查一个数是否等于其因子的和,需要遍历因子。 16. 图形输出:控制字符输出,理解嵌套循环。 17. 条件输出图形:根据条件调整输出,涉及多层...

    专升本C++复习题.pdf

    5. **水仙花数**:水仙花数是指一个n位数,其各位数字的n次方之和等于数字本身。可以使用循环和幂运算来检查每个n位数。 6. **回文数**:回文数是正读反读都一样的数。可以编写一个函数判断一个数是否为回文数,...

    java 算法示例

    水仙花数是三位数,且每位数的立方和等于该数本身。例如153=1^3+5^3+3^3。可以通过遍历100到999的数字,逐个检查是否满足条件。 【程序4】质因数分解。将一个正整数n分解为质因数的乘积。使用循环和条件判断,从2...

    java基础练习题

    **知识点**: 可以通过不断除以10的方式减少数字的位数,直到结果小于10。 ```java int num = 12345; int count = 0; do { num /= 10; count++; } while (num &gt;= 10); System.out.println("位数:" + count); ``` ...

    PASCAL竞赛试题汇编.pdf

    10. 数字特性:寻找“水仙花数”,需要遍历三位数,检查每个数是否满足条件。 11. 序列规律:通过观察序列的规律,填空并打印算式,考察逻辑推理和数学归纳能力。 12. 鸡兔同笼问题:分配不同价格的鸡、兔数量,...

    非常好的Java练习题

    9. **水仙花数**:遍历三位数,检查每位数的立方和是否等于原数。 10. **数字字符串相加**:字符串处理,通过循环和累加计算多位数的和。 11. **完数查找**:遍历一定范围内的数,检查因子之和是否等于原数。 12....

    c语言试题100道.doc

    25. **水仙花数**:检查三位数的每一位立方和是否等于原数。 26. **鸡兔同笼问题**:使用线性代数解决,建立方程组求解。 27. **人民币兑换**:组合优化问题,通过穷举所有可能的硬币组合找到满足条件的方案。 28. *...

    Java50道经典题目

    - **知识点**: 水仙花数是指一个三位数,其各位数字立方和等于该数本身(如153 = 1^3 + 5^3 + 3^3)。 - **实现方法**: - 遍历100到999之间的所有三位数。 - 对每个数进行分解,分别计算百位、十位、个位数字。 -...

    c语言作业题

    - **解析**: 输出所有水仙花数,即那些各位数字立方和等于其本身的三位数。涉及到循环结构的设计以及数值运算。 **E25. 循环嵌套、穷举法** - **知识点**: 穷举法、循环结构。 - **解析**: 寻找支付50元商品的所有...

Global site tag (gtag.js) - Google Analytics