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

如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占一行。因为这个数字很大,请注意解法时间上的可行性。


优化:不管一个数是多少位,它都是由0~9这10个数字组成,所以我们可以先分别求出这10个数的各自的21次方,

           又因为10个9的21次方之和超过了21位数,所以从9个9,12个8开始一次往下运算即可


这个题意我是看懂了,上网百度了一下别人的代码,但是有三处我看不懂。


#include <iostream>
#include <stdio.h>
#include<time.h>
#include <string.h>
using namespace std;
int A[10][21],count[100][21],cnt=0;
void Get()//将0-9这10个数的每个数的21次方存入A数组
{
    memset(A,0,sizeof(A));
    for(int k=0; k<10; k++) //一共有10个数
    {
        A[k][20]=1;  //因为是乘法所以每个数的底数设为1
        int sum=0;
        for(int i=1; i<=21; i++) //21次方
        {
            for(int j=20; j>=0; j--)
            {
                sum=sum+A[k][j]*k;
                A[k][j]=sum%10;
                sum=sum/10;
            }
        }
    }
}
void Cal()
{
    int B[21]; //b[N]存从99……99到100……00之间的数 初始化为9个9后面全是8,因为10个9的21次方之和将超过21位数
    for(int i=0; i<9; i++)  B[i]=9;
    for(int i=9; i<21; i++) B[i]=8;

    while(B[0]!=0)
    {
        int flag=1;
        int sum[21]= {0},sort[21]= {0},E[10]= {0};
        for(int i=0; i<21; i++) //求B中21个数的21次方之和
        {
            int temp=0;
            for(int j=20; j>=0; j--)
            {
                temp=temp+A[B[i]][j]+sum[j];
                sum[j]=temp%10;
                temp=temp/10;
                if(j==0&&temp>0)
                {
                    flag=0;
                    break;//位数超过21位舍弃
                }
            }
            if(flag==0)break;
        }
        if(sum[0]==0) flag=0;//位数不够21位舍弃

        if(flag==1)//位数正好21位看看两个数是不是相等
        {
            for(int i=0; i<21; i++)         
                E[sum[i]]++;     //统计sum中分别有几个0到9 存到E[N]中
            for(int i=9,x=0; i>=0; i--)
                for(int j=0; j<E[i]; j++)
                    sort[x++]=i;
            //比较二者是否相等
            for(int i=0; i<21; i++)
            {
                if(B[i]!=sort[i])  //难处1:这个B不应该跟sum比较吗,关sort什么事
                {
                    flag=0;
                    break;
                }
            }
        }
        if(flag==1)//两个数相等就存起来
        {
            for(int j=0; j<21; j++)
                count[cnt][j]=sum[j];//若这个地方换成了count[cnt][j]=B[j]那结果直接就不对,根据题意B应该跟sum是一样的??????
            cnt++;
        }

        //找下一个B[N]  (找下一个B的找法我是一点都不理解啊)
        int i;
        for(i=20; i>=0; i--)
            if(B[i]!=0)
                break;
        int temp=B[i];
        while(i<21)
        {
            B[i++]=temp-1; //保证去掉重复的数  并按从大到小顺序 进行处理(尤其是这个地方直接不懂怎么去的重复的数)
        }
    }
    for(int i=cnt-1; i>=0; i--)
    {
        for(int j=0; j<21; j++)
            cout<<count[i][j];
        cout<<endl;
    }
}
int main()
{
    Get();
    Cal();
    printf("\n程序运行了%.2lf秒\n",(double)clock()/CLOCKS_PER_SEC);//只是为了测试一下程序运行的时间
    return 0;
}



posted on 2015-04-07 18:00  星斗万千  阅读(392)  评论(0)    收藏  举报