| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3341 人关注过本帖
标题:21位水仙花数优化问题
只看楼主 加入收藏
daydreary
Rank: 2
等 级:论坛游民
帖 子:15
专家分:37
注 册:2012-2-15
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:8 
21位水仙花数优化问题
自己写了个求出21位水仙花数的程序,运行时间在我的电脑上41秒左右,想请教下高手怎么再优化一下程序,大概谈谈思路就可以,谢谢。
我的思路是这样,任何一个水仙花数,比如153=1^3+5^3+3^3,里面包括1个1,1个5,1个3。如果是513,315,351……,这几个数字中1,3,5出现的次数和水仙花数是一样的……那么513,315,351这些数字,每位上数字的和应该就是水仙花数。
代码:
程序代码:
#include <stdio.h>
#include <time.h>
int num_time[10]={0};  //num_time[10]用来得到0-9数字出现的个数
int sum[10][21]={(0,0)},sumc[10][21]={(0,0)};//sum数组用来计算出0-9的21次方。sumc用来计算数字出现次数*它的21次方
int count=0;   //计算得到几个水仙花数了,得到2个以后就结束程序

void initProgramm()  //这个函数用来获得0-9的21次方,存在sum数组里
{
    int i,j,k;
    for(i=0;i<10;i++)
        sum[i][20]=i;

    for(k=2;k<10;k++)
    {
        for(i=1;i<21;i++)
        {
            for(j=20;j>=0;j--)
            {
                sum[k][j]*=k;
            }
            for(j=20;j>0;j--)
            {
                sum[k][j-1]+=sum[k][j]/10;
                sum[k][j]%=10;
            }
        }
    }
}


void check(int i0,int i1,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9) //检测数字是不是水仙花数
{
    int i,j;
    int getAdd[21]={0};

       for(j=0;j<21;j++)             //把数字出现次数*它的21次方
    {
           sumc[1][j]=sum[1][j]*i1;
           sumc[2][j]=sum[2][j]*i2;
        sumc[3][j]=sum[3][j]*i3;
        sumc[4][j]=sum[4][j]*i4;
        sumc[5][j]=sum[5][j]*i5;
        sumc[6][j]=sum[6][j]*i6;
        sumc[7][j]=sum[7][j]*i7;
        sumc[8][j]=sum[8][j]*i8;
        sumc[9][j]=sum[9][j]*i9;
    }

       for(i=0;i<10;i++)     //进位
        for(j=20;j>0;j--)
        {
            sumc[i][j-1]+=sumc[i][j]/10;
            sumc[i][j]%=10;
        } 

    for(i=0;i<10;i++)       //得到一个数每位的21次方的和,就是把sumc叠加起来
        for(j=20;j>=0;j--)
            getAdd[j]+=sumc[i][j];
   
    for(i=20;i>0;i--)    //进位
    {
        getAdd[i-1]+=getAdd[i]/10;
        getAdd[i]%=10;
    }
   
    int j1=0,j2=0,j3=0,j4=0,j5=0,j6=0,j7=0,j8=0,j9=0,j0=0; 
    for(i=20;i>=0;i--)          //用来判断和里面每个数字出现的次数
    {
        switch(getAdd[i])
        {
            case 0:j0++;break;
            case 1:j1++;break;
            case 2:j2++;break;
            case 3:j3++;break;
            case 4:j4++;break;
            case 5:j5++;break;
            case 6:j6++;break;
            case 7:j7++;break;
            case 8:j8++;break;
            case 9:j9++;break;
        }
    }
   
    //如果一个数字,和里0-9出现的次数与这个数字里0-9出现的次数相同,那么和就应该是水仙花数(第一位数字不能为0)。
    if((i0==j0)&&(i1==j1)&&(i2==j2)&&(i3==j3)&&(i4==j4)&&(i5==j5)&&(i6==j6)&&(i7==j7)&&(i8==j8)&&(i9==j9)&&(getAdd[0]!=0))
    {
        printf("\n");
        count++;
        for(i=0;i<21;i++)
            printf("%d",getAdd[i]);
        printf("\n");
    }
}

void main()
{
    int t,t1,t2;
    initProgramm();
    t1=time(NULL);
    int i0,i1,i2,i3,i4,i5,i6,i7,i8,i9;
    for(i9=0;i9<10;i9++)    //10层循环进行枚举,判断
    {
        for(i0=1;i0<22;i0++)
        {
            if(count==2)   //出现2个水仙花数以后break
                break;
            if(i9+i0==21)
            {    check(i0,0,0,0,0,0,0,0,0,i9);break;} //几个数字的出现次数和为21以后就break,因为后面的数字出现次数和一定大于21位
            for(i2=0;i2<22;i2++)
            {
                if(count==2)
                    break;
                if(i9+i0+i2==21)
                {    check(i0,0,i2,0,0,0,0,0,0,i9);break;}
                for(i3=0;i3<22;i3++)
                {
                    if(count==2)
                        break;
                    if(i9+i0+i2+i3==21)
                    {    check(i0,0,i2,i3,0,0,0,0,0,i9);break;}
                    for(i4=0;i4<22;i4++)
                    {
                        if(count==2)
                            break;
                        if(i9+i0+i2+i3+i4==21)
                        {    check(i0,0,i2,i3,i4,0,0,0,0,i9);break;}
                        for(i5=0;i5<22;i5++)
                        {
                            if(count==2)
                                break;
                             if(i9+i0+i2+i3+i4+i5==21)
                            {    check(i0,0,i2,i3,i4,i5,0,0,0,i9);break;}
                            for(i6=0;i6<22;i6++)
                            {
                                if(count==2)
                                    break;
                                if(i9+i0+i2+i3+i4+i5+i6==21)
                                {    check(i0,0,i2,i3,i4,i5,i6,0,0,i9);break;}
                                for(i7=0;i7<22;i7++)
                                {
                                    if(count==2)
                                        break;
                                    if(i9+i0+i2+i3+i4+i5+i6+i7==21)
                                    {    check(i0,0,i2,i3,i4,i5,i6,i7,0,i9);break;}
                                    for(i8=0;i8<22;i8++)
                                    {
                                        if(count==2)
                                            break;
                                        if(i9+i0+i2+i3+i4+i5+i6+i7+i8==21)
                                        {    check(i0,0,i2,i3,i4,i5,i6,i7,i8,i9);break;}
                                        for(i1=0;i1<22;i1++)
                                        {
                                            if(count==2)
                                                  break;
                                            if(i9+i0+i2+i3+i4+i5+i6+i7+i8+i1==21)
                                            {    check(i0,i1,i2,i3,i4,i5,i6,i7,i8,i9);break;}
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    t2=time(NULL);
    t=t2-t1;
    printf("\n%d s\n",t);
}

搜索更多相关主题的帖子: 数字 优化 水仙花 color 
2012-02-17 20:58
转角有梦在等
Rank: 2
来 自:黑龙江
等 级:论坛游民
帖 子:31
专家分:95
注 册:2012-2-4
收藏
得分:5 
哈哈, 网上有好多 你要好对对代码 有很多高深的

一起努力,,,  QQ:7325231
2012-02-17 21:14
daydreary
Rank: 2
等 级:论坛游民
帖 子:15
专家分:37
注 册:2012-2-15
收藏
得分:0 
回复 2楼 转角有梦在等
网上是有不少,挺厉害的,不过我能力有限,那些有的地方看不明白
2012-02-17 21:19
xdh0817
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:193
专家分:195
注 册:2011-10-20
收藏
得分:5 
挣分
2012-02-18 09:51
chihuyu
Rank: 2
等 级:论坛游民
帖 子:70
专家分:13
注 册:2011-12-26
收藏
得分:5 
135是水仙花数,315是吗? 看看水仙花的定义
2012-02-18 10:14
daydreary
Rank: 2
等 级:论坛游民
帖 子:15
专家分:37
注 册:2012-2-15
收藏
得分:0 
回复 5楼 chihuyu
没说315是,但是315分解成3个数字以后,3^3+1^3+5^3=153,这个153就是,这样算就比一个一个枚举快多了
2012-02-18 10:22
漩涡鸣人——
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2012-2-5
收藏
得分:0 
楼主,我在网上找到一个程序,一直没看懂,谢谢你给了我一点思路。说说你的程序吧,思路不错,但在41秒,时间上有点自欺,你是在知道答案基础上优化的,如果不知道,你从哪里可以推断出符合条件只有2个呢?一下是我搜到的程序,你看看,和你思路类似,80多秒,有新想法请告诉我,共同进步,谢谢
#include<stdio.h>
#include<time.h>
int z[10][22];
void nef()
{
    int temp,i,j,m;
    for(i=0;i<10;i++)
    {
        z[i][0]=1;
    }
    for(i=0;i<10;i++)
    {
        for(j=0;j<21;j++)
        {
            m=0;
            temp=0;
            for(m=0;m<21;m++)
            {
            temp=temp/10+z[i][m]*i;
            z[i][m]=temp%10;
            }
        }
    }
    for(i=0;i<10;i++)
    {
        for(j=21;j>=0;j--)
            if(z[i][j]!=0)
                break;
            z[i][21]=j+1;
    }
}
void fun()
{
    int a[21]={0},b[21]={0},c[21]={0},d[21]={0},i,j,x,temp,f=0;
    a[20]=1;
    while(a[0]!=9)
    {//求和!
        for(i=0;i<21;i++)
        {
            temp=0;
            for(x=0;x<21;x++)
            {
                temp=b[x]+z[a[i]][x]+temp;
                b[x]=temp%10;
                temp=temp/10;
                if(temp==0&&x>=z[a[i]][21])
                    break;
            }
        }
        //排序
        for(i=0;i<21;i++)
            d[b[i]]++;
        x=0;
        for(i=0;i<10;i++)
        {
            for(j=0;j<d[i];j++)
            {
                c[x]=i;
                x++;
            }
        }
        //比较
        f=0;
        for(i=0;i<21;i++)
        {
            if(a[i]!=c[i])
            {
                f=a[i]-c[i];
                break;
            }
        }
        //如果相等输出
        if(f==0&&b[20]>=1&&b[20]<=9)
        {
            for(i=20;i>=0;i--)
                printf("%d",b[i]);
            printf("\n");
        }
        for(i=20;i>0;i--)
        {
            if(a[i]!=9)
                break;
        }
        temp=a[i];
        while(i<21)
        {
            a[i]=temp+1;
            i++;
        }
        for(i=0;i<21;i++)
        {
            b[i]=0;
            c[i]=0;
        }
        for(i=0;i<10;i++)
        {
            d[i]=0;
        }
    }
}
void main()
{
    int start=time(NULL),end;
    printf("程序开始进行\n");
    nef();
    fun();
    end=time(NULL);
    printf("这个程序共进行%d秒\n",end-start);
}
2012-04-04 16:54
漩涡鸣人——
Rank: 1
等 级:新手上路
帖 子:6
专家分:0
注 册:2012-2-5
收藏
得分:0 
回复 7楼 漩涡鸣人——
累加和的最高位getAdd[0]大于9你是不是也没有考虑啊?
2012-04-04 19:26
as6225442
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2013-3-6
收藏
得分:0 
纠结了好几天看到楼主的代码 我终于懂21为水仙花怎么弄了、、、

甚是厉害、、

 那个 i8

 for(i8=0;i8<22;i8++)可以剪枝把  程序效率还可以提高点
2013-03-06 22:22
快速回复:21位水仙花数优化问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.022660 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved