花朵数c语言算法,21位花朵数(详解)

今天看到了,蓝桥杯上面的一道题,求21位花朵数,题目是:

l  (编程题)花朵数

一个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次方之和正好等于这个数本身。

如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占一行。因为这个数字很大,请注意解法时间上的可行性。要求程序在3分钟内运行完毕。

【程序运行参考结果】

128468643043731391252

449177399146038697307

解:

本题的思路:

1:关键是:去掉所含0-9数字个数相同的21位数,以免重复运算,增加时间,比如123456789012345678901与987654321098765432101与987654321012345678901中的所含数字的个数都是相同的,所以其每一位的21次方的和都相等,将所得的21次方和 从大到小进行排序,若对应的数与原数不相等,则都不成立,因此若不去掉重复的数,将会增加运算时间;

2:以为要将每一位数的21次方之和从大到小排序,所以运算从21个9这个最大数开始向下运算,又因为10个9的21次方之和超过了21位数,所以从9个9,12个8开始一次往下运算即可,这样又可以节约一部分时间。

fcecaa27ea5212ceb9bf034c36bfbf34.gif

#include

#include

#include

//#include

//#include

//有的注释 是用来测试数据

#define N 21

int a[10][N+1];

void fun()

{

int i,temp,j,k;

for(i=0;i<10;i++)//对0-9每个数的21次方 分别存入数组a[i][N+1]中

{

a[i][0]=1;

for(k=0;k

{

temp=0;

for(j=0;j

{

temp=temp/10+a[i][j]*i;

a[i][j]=temp%10;

}

}

}

for(i=0;i<10;i++)

{

for(j=N-1;j>=0;j--)

if(a[i][j]!=0)break;

a[i][N]=j+1; //记录从第几个开始之后全部为0

}

//可以在此处输出结果以供检查错误

/*for(i=0;i<10;i++)

{

printf("i=%d\n",i);

for(j=0;j

printf("%3d",a[i][j]);

printf("\n");

}*/

}

void fun1()

{

int b[N];

int c[N]={0},d[N]={0},e[10]={0};//c[N]存b[N]中每个数字的21次方之和

int x,i,j,k,temp,flag; //d[N]存c[N]从大到小排好序的值

int f[100][21]; //用来存放满足条件的数 然后从小到大输出

for(i=0;i<9;i++) //b[N]存从99……99到100……00之间的数 初始化为9个9后面全是8,因为10个9的21次方之和将超过21位数

b[i]=9;

for(i=9;i

b[i]=8;

k=0;//先将满足条件的数组个数清为0

while(b[0]!=0) //e[N]存中间排序的中间量 选择的排序方法比较特别(已知最大值的排序)

{

flag=1;

//求21个数的21次方之和

for(i=0;i

{

temp=0;

for(j=0;j

{

temp=temp/10+a[b[i]][j]+c[j];

c[j]=temp%10;

if(j==N-1&&temp>9) //

{

flag=0;

//printf("超过21位数\n");

break;

}

if(a[b[i]][j]==0&&j>=a[b[i]][N])break;//

}

if(flag==0)break;// 这些都是为了节省时间 进行程序优化

}

//getch();

if(c[N-1]==0)flag=0;

if(flag)

{

//将c[N]排序 注意排序方法 复杂度较低

x=0;

for(i=0;i

e[c[i]]++; //分别有几个0到9 存到e[N]中 曾将c[i]错写成b[i]~~

for(i=10-1;i>=0;i--)

{

for(j=0;j

d[x++]=i;

}

//比较二者是否相等

for(i=0;i

{

if(b[i]!=d[i])

{

flag=0;

break;

}

}

}//if

//如果标记falg=1则输出结果

if(flag)

{

/*printf("输出结果为:");

for(i=N-1;i>=0;i--)

printf("%d",c[i]); 将c[i]曾错写成b[i]

printf("\n");若这样输出则为从大到小输出*/

j=0;

for(i=N-1;i>=0;i--)

f[k][j++]=c[i];

k++;

}

//找下一个a[N]

for(i=N-1;i>=0;i--)

if(b[i]!=0) //此处曾经出错 将b[i]写成a[i]

break;

temp=b[i];

// printf("temp=%d ",temp);

while(i

{

b[i++]=temp-1; //保证去掉重复的数 并按从大到小顺序 进行处理

}

//printf("b[2]=%d b[3]=%d\n",b[2],b[3]);

memset(c,0,sizeof(c));//全部置0 因为后面还要用

memset(d,0,sizeof(d));

memset(e,0,sizeof(e));

}

//从小到大输出

for(i=k-1;i>=0;i--)

{

for(j=0;j

printf("%d",f[i][j]);

printf("\n");

}

}

int main()

{

fun();

fun1();

printf("\n程序运行了%.2lf秒\n",(double)clock()/CLOCKS_PER_SEC);//只是为了测试一下程序运行的时间

return 0;

}

fcecaa27ea5212ceb9bf034c36bfbf34.gif

程序运行结果:

519682b9124bea5f002d07f4cb80a9d2.png

此题目应该还可以再优化,不过已经很满足了题目要求。若谁有更为简单的方法,别忘了与大家共享哦!

~~ 转载请注明出处^^

原文:http://www.cnblogs.com/DreamStarrySky/p/4985901.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值