21位花朵数(详解)

转载自http://www.cnblogs.com/hsqdboke/archive/2012/04/14/2447079.html#3306648

~~ 转载请注明出处^^

今天看到了,蓝桥杯上面的一道题,求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开始一次往下运算即可,这样又可以节约一部分时间。

#include<stdio.h>
#include<time.h>
#include<string.h>
//#include<conio.h>
//#include<math.h>
//有的注释 是用来测试数据
#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<N;k++)
     {
         temp=0;
         for(j=0;j<N;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<N+1;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<N;i++)
     b[i]=8;
     k=0;//先将满足条件的数组个数清为0
    while(b[0]!=0)    //e[N]存中间排序的中间量 选择的排序方法比较特别(已知最大值的排序)
    {
        flag=1;

        //求21个数的21次方之和
        for(i=0;i<N;i++)
        {
            temp=0;
            for(j=0;j<N;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<N;i++)
         e[c[i]]++; //分别有几个0到9 存到e[N]中  曾将c[i]错写成b[i]~~
        for(i=10-1;i>=0;i--)
        {
         for(j=0;j<e[i];j++)
              d[x++]=i;
        }

        //比较二者是否相等
        for(i=0;i<N;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<N)
        {
            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<N;j++)
         printf("%d",f[i][j]);
         printf("\n");
     }
}
int main()
{
    fun();
    fun1();

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

程序运行结果:

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

~~ 转载请注明出处^^

时间: 2024-10-23 12:35:21

21位花朵数(详解)的相关文章

21位花朵数

#include"stdio.h"#include<math.h>main(){ int q[21],p[21],j,n,w,o,s; double sum1,sum2; long int i; A: printf("请输入数的位数:\n"); scanf("%d",&w); for (i=pow(10,w-1),o=pow(10,w)-1;i+1!=o;i++,o--) { for (j=0,n=i,s=o;j<w;j

sar-iostat-vmstat-参数详解

sar sar 是分析系统性能的重要工具之一,通过sar指令可以全面地获取系统的CPU运行队列.磁盘I/O.分页(交换分区).内存.CPU 中断网络等性能数据. sar [options] [-o filename] [interval count] options:  -A:显示系统所有资源设备,CPU.内存.磁盘 的运行状态.  -u:显示系统所有CPU 采样的负载.  -P:显示当前系统中指定CPU的使用情况  -d:显示系统所有硬盘设备在采样时间内的使用状况.  -r:显示系统内存在采样

Python基础03-函数详解

Python函数详解 这次内容包含: 函数 模块 文件操作 异常处理 函数: 认识函数 局部变量与全局变量 函数参数使用详解 函数使用实战 函数的本质就是功能的分装.比如 我们封装一个求a的2次方的函数c=a*a.如果我们求2次方变可以使用这个函数了(只是打比方). Python中pow(x,y)就是求x的y次方的函数. 作用:提供编程效率与程序的刻度性 局部变量与全局变量 变量有生效范围,范围就是作用域. 全局变量:作用域从变量出现开始到程序的最末的变量就做全局变量 局部变量:作用域只在局部的

PLSQL Developer连接Oracle11g 64位数据库配置详解

1. 下载instantclient-basic-win32-11.2.0.1.0(oracle官网下载地址:http://www.oracle.com/technetwork/topics/winsoft-085727.html , 下载地址2:http://download.csdn.net/detail/czw2010/5732241) 2. 解压instantclient-basic-win32-11.2.0.1.0并放置在oracle安装目录 3. 打开PLSQL Developer,

phpcms推荐位数据库字段详解

这个对应的数据库中的表是 v9_position 字段说明: Posid : 推荐位ID Modelid : 适用的模型ID,0即为全部模型 Catid  :栏目ID Name :名称 Maxnum : 最大存储数量 Extention : Listorder :排序 Siteid : 站点ID Thumb :图片 子表保存在v9_position_data 字段说明: Id :该条数据在数据库中的ID Catid : 栏目ID Posid : 对应父表的posid Module : 模块 Mo

【转】Linux中的特殊权限粘滞位(sticky bit)详解

在linux下每一个文件和目录都有自己的访问权限,访问权限确定了用户能否访问文件或者目录和怎样进行访问.最为我们熟知的一个文件或目录可能拥有三种权限,分别是读.写.和执行操作,在这里不做详细说明.我们创建一个文件后系统会默认地赋予所有者读和写权限.当然我们也可以自己修改它,添加自己需要的权限. 特殊权限 但是这三种权限就足够了吗?我们现在来说说在linux下的另一个特殊权限.首先我们来看看在根目录下的一个目录tmp,可以看到tmp目录的other权限是'rwt',那么这里的t又是什么权限呢,有什

xcopy-参数详解

XCOPY--目录复制命令 1.功能:复制指定的目录和目录下的所有文件连同目录结构. 2.类型:外部命令 3.格式:XCOPY [源盘:]〈源路径名〉[目标盘符:][目标路径名][/S][/V][/E] 4.使用说明: (1)XCOPY是COPY的扩展,可以把指定的目录连文件和目录结构一并拷贝,但不能拷贝隐藏文件和系统文件: (2)使用时源盘符.源目标路径名.源文件名至少指定一个: (3)选用/S时对源目录下及其子目录下的所有文件进行COPY.除非指定/E参数,否则/S不会拷贝空目录, 若不指定

数学、计算几何、位运算常见问题详解

? 矩阵上的问题(3题) Search a 2D Matrix II public int searchMatrix(int[][] matrix, int target) { // write your code here int n = matrix.length; if (n == 0) { return 0; } int m = matrix[0].length; if (m == 0) { return 0; } int i = n - 1; int j = 0; int res =

零基础入门Python3-函数详解(1)

我们通过一种运算方法,把一个数字运算成另一个数字,每次需要运算的数字都是不同的,但是运算方法都是一致的.如果每次运算都需要定义和编写相同代码,那我们的工作量简直太大了.函数就是对应的解决办法,输入对象,通过相同的计算,得到相应的结果,这个调用过程就叫做函数. 1.定义函数 def 函数名称():         语句1         语句2         ......         return xxx def是定义函数的标识,这个是不能丢的.然后函数名称和变量定义的规则是一致的,不能以数