| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3434 人关注过本帖, 1 人收藏
标题:(C编程题)花朵数
只看楼主 加入收藏
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
唉,小曹从医可惜了,他的兴趣全在算法上

重剑无锋,大巧不工
2011-12-25 23:23
czz5242199
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:660
专家分:2400
注 册:2011-10-26
收藏
得分:0 
回复 11楼 beyondyf
还好,这个平时学学也不错。

纪念我第一次通宵学习,居然是复习人解的

连续看人解已经快18h了
2011-12-26 06:04
czz5242199
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:660
专家分:2400
注 册:2011-10-26
收藏
得分:0 
回复 10楼 laoyang103
应该是C(30,9),这个打印的是x0+x1+...x9=21的解的数目

[ 本帖最后由 czz5242199 于 2011-12-26 06:39 编辑 ]
2011-12-26 06:22
strivelong87
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:68
专家分:159
注 册:2011-11-24
收藏
得分:3 
这不水仙花吗?
2011-12-26 08:24
waterstar
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:5
帖 子:984
专家分:2810
注 册:2010-2-12
收藏
得分:3 
回复 12楼 czz5242199
曹兄弟,我真该和你握个手,当年我学人体解剖学的时候也是一样的痛苦

冰冻三尺,非一日之寒;士别三日,不足刮目相看!
2011-12-26 11:08
waterstar
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:5
帖 子:984
专家分:2810
注 册:2010-2-12
收藏
得分:0 
程序代码:
//水仙花数
//21位
#include <stdio.h>
#include <time.h>
#define    N 10
const int Pow[10][21] = {{0}, {1}, {2, 5, 1, 7, 9, 0, 2},

                        {3, 0, 2, 3, 5, 3, 0, 6, 4, 0, 1},

                        {4, 0, 1, 1, 1, 5, 6, 4, 0, 8, 9, 3, 4},
                        {5, 2, 1, 3, 0, 2, 8, 5, 1, 7, 3, 8, 6, 7, 4},

                        {6, 5, 8, 7, 7, 3, 0, 4, 6, 0, 5, 9, 6, 3, 9, 1, 2},

                        {7, 0, 0, 4, 8, 2, 3, 8, 0, 4, 6, 8, 5, 4, 5, 8, 5, 5},

                        {8, 0, 8, 5, 7, 7, 4, 5, 8, 6, 3, 0, 2, 7, 3, 3, 2, 2, 9},

                        {9, 0, 2, 9, 5, 3, 2, 1, 5, 1, 3, 1, 9, 8, 9, 8, 1, 4, 9, 0, 1}};
void narciss ();
void add (int *, int);
void sub (int    *sum, const int num);
void SumNumber (int *sum, int * pstack);
int    cmp (int    *a, int        *b);


int main ()
{
    clock_t        start, end;
    int            n = 1;

    start = clock ();
    narciss ();
    end = clock ();
    printf ("%.3lfs\n", (double)(end - start) / CLK_TCK);

    return 0;
}

void narciss ()
{
    int        iSumNum[N] = {0};
    int        iStackNum[N] = {0};
    int        iSum[22] = {0};   

    int        iStack[22] = {0};
    int        *top = iStack;
    int    * const maxTop = iStack + 21;
    int        flag = 0;
    int        k = 9;
    int        i;

    while (1)
    {
        if (top < maxTop && iSum[21] == 0)
        {
            add (iSum, k);
            *top++ = k;
            iStackNum[k]++;
        }

        if (iSum[21] > 0)
        {
            sub (iSum, k);
            iStackNum[k]--;
            top--;
            k = *top - 1;
        }

        if (top == maxTop)
        {
            if (0 == iSum[20])
                break;
            SumNumber (iSum, iSumNum);

            if (cmp (iSumNum, iStackNum))
            {
                for (i = 20; i >= 1; i--)
                    printf ("%d", iSum[i]);
                printf ("\n");
            }

            if (0 != *(top - 1))
            {
                sub (iSum, k);
                iStackNum[k]--;
            }
            else
            {
                while (0 == *(top - 1))
                {
                    top--;
                    iStackNum[0]--;
                }
                flag = 1;
            }
            k = *--top;
            if (flag)
            {
                sub (iSum, k);
                iStackNum[k]--;
                flag = 0;
            }
            k--;
        }
    }
}

void add (int    *sum, const int    num)
{
    int        i;
//    const int j = num * 21;

    for (i = 0; i < 21; i++)
        sum[i] += Pow [num][i];
    for (i = 0; i < 21; i++)
    {
        if (sum[i] > 9)
        {
            sum[i + 1] += sum[i] / 10;
            sum[i] = sum[i] % 10;
        }
    }
}

void sub (int    *sum, const int num)
{
    int        i;
    for (i = 0; i < 21; i++)
    {
        if (sum[i] < Pow[num][i])
        {
            sum[i + 1] -= 1;
            sum[i] = sum[i] + 10 - Pow[num][i];
        }
        else
        {
            sum[i] -= Pow[num][i];
        }
    }
}

void SumNumber (int *sum, int * pstack)
{
    int len = 21;
    memset (pstack, 0, sizeof (int) * N);

    while (len--)
    {
        pstack[*sum++]++;
    }
}

int    cmp (int    *a, int        *b)
{
    int i;
    for (i = 0; i < N; i++)
        if (a[i] != b[i])
            return 0;

    return 1;
}
刚完成,太笨了,用了一个下午的时间,求21位的水仙花数用12秒多,还有改进的空间。



冰冻三尺,非一日之寒;士别三日,不足刮目相看!
2011-12-26 17:07
czz5242199
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:660
专家分:2400
注 册:2011-10-26
收藏
得分:0 
回复 16楼 waterstar
这。你写个程序最好介绍一下基本算法思路,否则看起来太麻烦了

你这个貌似是手动递归写的一个什么没看大明白
2011-12-26 17:19
waterstar
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:5
帖 子:984
专家分:2810
注 册:2010-2-12
收藏
得分:0 
回复 17楼 czz5242199
确实是手动写递归过程,为了提高运行速度。
简单讲下思路吧
首先是从大数到小数的思想,从9开始,最多要用到多少个9,多于这个数的结果就必然超出21位数了,然后逐个递减9的数目,增加其他数的数目,求和之后看看是否超过21位,超过就下降试探值,继续试探。结束条件是到达某个值后,发现其和不等于21位,则比它的个头小的数必然无法满足条件,可以结束运算。
讲的不是很清楚,举个例子吧
假设128468643043731391252 这个数是最后一个各位数的21次方和能达到21位的数,那么可以看出其有1个9,也就是说没有9的情况直接被枪毙掉了,不用考虑。
iSumNum,iStackNum用来存放0~9这十个数出现的次数,只要这两个数组相同,就认为是水仙花数
iSum用来存放每次的计算值,iStack存放的是总试探值,iStack中值的21次方数就是iSum中的值(当然这只是泛泛而言),试探值是k。
感觉越解释越不清楚,有什么不懂的直接问吧。

冰冻三尺,非一日之寒;士别三日,不足刮目相看!
2011-12-26 17:44
laoyang103
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
注 册:2010-5-22
收藏
得分:0 
回复 13楼 czz5242199
x0+x1+...x9=21的解的数目应该是C(30,9)

可否解释一下

                                         
===========深入<----------------->浅出============
2011-12-26 19:01
czz5242199
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:660
专家分:2400
注 册:2011-10-26
收藏
得分:0 
回复 19楼 laoyang103
x0+x1+..x9=21 (xi>=0)
令yi=xi+1
y0+y1+..y9=31 (yi>=1)
上面的这个方程利用排列组合就是30空选9个做隔板C(30,9)
2011-12-26 19:20
快速回复:(C编程题)花朵数
数据加载中...
 
   



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

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