/*(编程题)花朵数
一个N位的十进制正整数,如果它的每个位上的数字的N次方的和等于这个数本身,则称其为花朵数。
例如:
当N=3时,153就满足条件,因为 1^3 + 5^3 + 3^3 = 153,这样的数字也被称为水仙花数(其中,“^”表示乘方,5^3表示5的3次方,也就是立方)。
当N=4时,1634满足条件,因为 1^4 + 6^4 + 3^4 + 4^4 = 1634。
当N=5时,92727满足条件。
实际上,对N的每个取值,可能有多个数字满足条件。
程序的任务是:求N=21时,所有满足条件的花朵数。注意:这个整数有21位,它的各个位数字的21次方之和正好等于这个数本身。
如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占一行。
*/
/*
大一的时候,写过三位水仙花数的程序作业,当时的思路是从100-999依次遍历,例如153,用/和%求出每位的数字,计算1^3+5^3+3^3的和,然后和原数比较,如果相等就输出。。。
这次又遇到了这种题,于是用了类似的解法,只不过是一位一位的构造,构造过程中顺便计算每一位的21次方的累加和,直到构造为21位数字。。。
这次写的代码,计算9位的花朵数需要50秒,计算21位的话,就算给它一首歌的时间也不够。。。
======================================================================================================
然后我看了别人的解法,看过之后我发现自己脑子真是不开窍。。。
======================================================================================================
*/
//我的代码
#include <stdio.h>
typedef __int64 INT;
#define N 8
INT N_pow[10];
INT Pow(INT x)
{
int i;
INT r=1;
if (x == 0) return 0;
for (i=0; i<N; i++) r*=x;
return r;
}
void flower(INT x_r,INT a_r,int n)
{
INT t=0,x=0,a=0,x_r8= x_r<<3,x_r2= x_r<<1;
if (n == 0)
{
if (x_r == a_r) printf("%I64d\n",x_r);
return;
}
if (x_r!=0 && t==0) flower(x_r2+x_r8+t,(a_r+N_pow[t]),n-1);
for (t=1;t<=9;t++) flower(x_r2+x_r8+t,(a_r+N_pow[t]),n-1);
}
void main()
{
INT add_r = 0;
INT x_r = 0;
int n=N;
INT i;
for (i=0;i<=9;i++) N_pow[i] = Pow(i);
flower(x_r,add_r,n);
}
//别人的思路
/*
1:21位花朵数,21个位置,0-9共10个数字,用这10个数字去填补21个位置并记录每个数字出现的次数;
2:21个位置填满之后,计算这21位数字每位数字的21次方的和sum【优化:sum不是21位就跳过】,然后统计sum中10个数字出现的次数;
3:对比1和2中得到的每个数字出现的次数是否相等【优化:不等就跳过】,如果相等,那么就输出sum即可。
效率:这种解法,计算出21位花朵数只要不到1分钟的时间。
*/
//结论:我知道的还很少~