求花朵数的C/C++快速算法!!高手赐教!

_青v菜_ 2011-04-25 11:37:19
一个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分钟内运行完毕。

...全文
1610 41 打赏 收藏 转发到动态 举报
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
bruceteen 2013-06-24
  • 打赏
  • 举报
回复
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <ctime>

struct Type
{
    Type( unsigned h, unsigned m, unsigned l ) : high(h), middle(m), low(l)
    {
    }
    Type( unsigned m, unsigned l ) : high(0), middle(m), low(l)
    {
    }
    Type( unsigned l ) : high(0), middle(0), low(l)
    {
    }

    static Type pow( unsigned base, unsigned power )
    {
        if( power==0 ) return Type(1);

        unsigned n, m=1;
        for( n=0; n<power && m*base<10000000; ++n )
            m *= base;

        unsigned a = 1;
        for( unsigned i=0; i<power%n; ++i )
            a *= base;

        Type t = a;
        for( unsigned i=0; i<power/n; ++i )
            t *= m;

        return t;
    }

    Type& operator+=( const Type& type )
    {
        low += type.low;
        unsigned carry = low/10000000;
        low%=10000000;

        middle += type.middle + carry;
        carry = middle/10000000;
        middle %= 10000000;

        high += type.high + carry;

        return *this;
    }
    Type operator+( const Type& type ) const
    {
        Type ret = *this;
        ret += type;
        return ret;
    }

    Type& operator+=( unsigned n )
    {
        low += n;
        unsigned carry = low/10000000;
        low%=10000000;

        middle += carry;
        carry = middle/10000000;
        middle %= 10000000;

        high += carry;

        return *this;
    }
    Type operator+( unsigned n ) const
    {
        Type ret = *this;
        ret += n;
        return ret;
    }

    Type& operator-=( const Type& type )
    {
        low = 10000000 + low - type.low;
        unsigned carry = low/10000000;
        low%=10000000;

        middle = 10000000 + middle + carry - 1 - type.middle;
        carry = middle/10000000;
        middle %= 10000000;

        high = high + carry - 1 - type.high;

        return *this;
    }
    Type operator-( const Type& type ) const
    {
        Type ret = *this;
        ret -= type;
        return ret;
    }

    Type& operator*=( unsigned n )
    {
        unsigned long long tmp = 1ull*low*n;

        unsigned long long carry = tmp/10000000;
        low = unsigned(tmp%10000000);

        tmp = 1ull*middle*n + carry;
        carry = tmp/10000000;
        middle = unsigned(tmp%10000000);

        high = unsigned(high*n + carry);

        return *this;
    }
    Type operator*( unsigned n ) const
    {
        Type ret = *this;
        ret *= n;
        return ret;
    }

    bool operator>( const Type& type ) const
    {
        if( high > type.high )
            return true;
        if( high < type.high )
            return false;

        if( middle > type.middle )
            return true;
        if( middle < type.middle )
            return false;

        return low>type.low;
    }
    bool operator>=( const Type& type ) const
    {
        if( high > type.high )
            return true;
        if( high < type.high )
            return false;

        if( middle > type.middle )
            return true;
        if( middle < type.middle )
            return false;

        return low>=type.low;
    }

    unsigned high, middle, low;
};

std::ostream& operator<<( std::ostream& os, const Type& type )
{
    return os << std::setfill('0') << std::setw(7) << type.high
              << std::setfill('0') << std::setw(7) << type.middle
              << std::setfill('0') << std::setw(7) << type.low;
}

const Type C[10] = { Type::pow(0,21), Type::pow(1,21), Type::pow(2,21), Type::pow(3,21), Type::pow(4,21), Type::pow(5,21), Type::pow(6,21), Type::pow(7,21), Type::pow(8,21), Type::pow(9,21) };
const Type minval = Type( 1000000, 0000000, 0000000 );
const Type maxval = Type( 9999999, 9999999, 9999999 );

int main()
{
    clock_t t0 = clock();

    unsigned num[10]   = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; // 起码得有1个9,否则达不到21位;且,有了1个9后,至少为21位
    Type overhead[10]  = { 0, 0, 0, 0, 0, 0, 0, 0, 0, maxval };
    unsigned total[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
    unsigned index     = 9;

    for( ; ; )
    {
        if( total[index]>21 || C[index]*num[index]>overhead[index] )
        {
            if( index == 9 )
                break;

            ++index;
            ++num[index];
            ++total[index];
            continue;
        }

        if( index == 1 )
        {
            Type val = maxval - overhead[index] + 1*num[index];
            { // 验证
                unsigned t[3] = { val.low, val.middle, val.high };
                unsigned m[10] = { 0 };
                for( unsigned i=0; i!=3; ++i )
                {
                    ++m[ t[i]/1%10 ];
                    ++m[ t[i]/10%10 ];
                    ++m[ t[i]/100%10 ];
                    ++m[ t[i]/1000%10 ];
                    ++m[ t[i]/10000%10 ];
                    ++m[ t[i]/100000%10 ];
                    ++m[ t[i]/1000000%10 ];
                }
                unsigned f;
                for( f=1; f<10 && m[f]==num[f]; ++f );
                if( f == 10 )
                {
                    std::cout << val << std::endl; // 未必是从小到大排序
                }
            }

            ++num[index];
            ++total[index];
            continue;
        }
        
        overhead[index-1] = overhead[index] - C[index]*num[index];
        total[index-1] = total[index];
        --index;
        num[index] = 0;
    }

    clock_t t1 = clock();
    printf( "%d.%03d\n", (t1/CLOCKS_PER_SEC), (t1%CLOCKS_PER_SEC*1000) );

    return 0;
}

// 128468643043731391252
// 449177399146038697307
// 1.625000
bruceteen 2013-06-21
  • 打赏
  • 举报
回复
#include <utility>
#include <iostream>
#include <iomanip>

struct Type
{
    Type( unsigned h, unsigned m, unsigned l ) : high(h), middle(m), low(l)
    {
    }
    Type( unsigned m, unsigned l ) : high(0), middle(m), low(l)
    {
    }
    Type( unsigned l ) : high(0), middle(0), low(l)
    {
    }

    Type& operator+=( const Type& type )
    {
        low += type.low;
        unsigned carry = low/10000000;
        low%=10000000;

        middle += type.middle + carry;
        carry = middle/10000000;
        middle %= 10000000;

        high += type.high + carry;

        return *this;
    }
    Type operator+( const Type& type ) const
    {
        Type ret = *this;
        ret += type;
        return ret;
    }

    Type& operator-=( const Type& type )
    {
        low = 10000000 + low - type.low;
        unsigned carry = low/10000000;
        low%=10000000;

        middle = 10000000 + middle + carry - 1 - type.middle;
        carry = middle/10000000;
        middle %= 10000000;

        high = high + carry - 1 - type.high;

        return *this;
    }
    Type operator-( const Type& type ) const
    {
        Type ret = *this;
        ret -= type;
        return ret;
    }

    Type& operator*=( unsigned n )
    {
        unsigned long long tmp = 1ull*low*n;

        unsigned long long carry = tmp/10000000;
        low = unsigned(tmp%10000000);

        tmp = 1ull*middle*n + carry;
        carry = tmp/10000000;
        middle = unsigned(tmp%10000000);

        high = unsigned(high*n + carry);

        return *this;
    }
    Type operator*( unsigned n ) const
    {
        Type ret = *this;
        ret *= n;
        return ret;
    }

    bool operator>( const Type& type ) const
    {
        if( high > type.high )
            return true;
        if( high < type.high )
            return false;

        if( middle > type.middle )
            return true;
        if( middle < type.middle )
            return false;

        return low>type.low;
    }
    bool operator>=( const Type& type ) const
    {
        if( high > type.high )
            return true;
        if( high < type.high )
            return false;

        if( middle > type.middle )
            return true;
        if( middle < type.middle )
            return false;

        return low>=type.low;
    }

    unsigned high, middle, low;
};

std::ostream& operator<<( std::ostream& os, const Type& type )
{
    return os << std::setfill('0') << std::setw(7) << type.high
              << std::setfill('0') << std::setw(7) << type.middle
              << std::setfill('0') << std::setw(7) << type.low;
}

const Type C[10] = { Type(                         0 )
                   , Type(                         1 )
                   , Type(                   2097152 )
                   , Type(             1046,  353203 )
                   , Type(           439804, 6511104 )
                   , Type(       4, 7683715, 8203125 )
                   , Type(     219, 3695064,  377856 )
                   , Type(    5585, 4586408, 3284007 )
                   , Type(   92233, 7203685, 4775808 )
                   , Type( 1094189, 8913151, 2359209 ) };

const Type minval = Type( 1000000, 0000000, 0000000 );
const Type maxval = Type( 9999999, 9999999, 9999999 );

// a*num^21>=minv && b*num^21>maxv && a<=residue && b<=residue+1
std::pair<unsigned,unsigned> foo( const Type& minv, const Type& maxv, unsigned num, unsigned residue )
{
    unsigned a=residue+1, b=residue+1;
    for( unsigned i=0; i<=residue+1; ++i )
    {
        Type val =  C[num]*i;

        if( a==residue+1 && val>=minv )
            a = i;

        if( val > maxv )
        {
            b = i;
            break;
        }
    }
    return std::pair<unsigned,unsigned>(a,b);
}

// 验证
bool bar( const Type& type, unsigned i9, unsigned i8, unsigned i7, unsigned i6, unsigned i5, unsigned i4, unsigned i3, unsigned i2, unsigned i1 )
{
    unsigned t[3] = { type.low, type.middle, type.high };
    unsigned m[10] = { 0, i1, i2, i3, i4, i5, i6, i7, i8, i9 };
    for( unsigned i=0; i!=3; ++i )
    {
        --m[ t[i]/1%10 ];
        --m[ t[i]/10%10 ];
        --m[ t[i]/100%10 ];
        --m[ t[i]/1000%10 ];
        --m[ t[i]/10000%10 ];
        --m[ t[i]/100000%10 ];
        --m[ t[i]/1000000%10 ];
    }
    for( unsigned i=1; i<10; ++i )
        if( m[i] != 0 )
            return false;
    return true;
}

int main()
{
    Type l9 = maxval;
    std::pair<unsigned,unsigned> r9 = foo( minval, l9, 9, 21 );
    for( unsigned i9=r9.first; i9<r9.second; ++i9 )
    {
        Type l8 = l9 - C[9]*i9;
        std::pair<unsigned,unsigned> r8 = foo( 0, l8, 8, 21-i9 );
        for( unsigned i8=r8.first; i8<r8.second; ++i8 )
        {
            Type l7 = l8 - C[8]*i8;
            std::pair<unsigned,unsigned> r7 = foo( 0, l7, 7, 21-i9-i8 );
            for( unsigned i7=r7.first; i7<r7.second; ++i7 )
            {
                Type l6 = l7 - C[7]*i7;
                std::pair<unsigned,unsigned> r6 = foo( 0, l6, 6, 21-i9-i8-i7 );
                for( unsigned i6=r6.first; i6<r6.second; ++i6 )
                {
                    Type l5 = l6 - C[6]*i6;
                    std::pair<unsigned,unsigned> r5 = foo( 0, l5, 5, 21-i9-i8-i7-i6 );
                    for( unsigned i5=r5.first; i5<r5.second; ++i5 )
                    {
                        Type l4 = l5 - C[5]*i5;
                        std::pair<unsigned,unsigned> r4 = foo( 0, l4, 4, 21-i9-i8-i7-i6-i5 );
                        for( unsigned i4=r4.first; i4<r4.second; ++i4 )
                        {
                            Type l3 = l4 - C[4]*i4;
                            std::pair<unsigned,unsigned> r3 = foo( 0, l3, 3, 21-i9-i8-i7-i6-i5-i4 );
                            for( unsigned i3=r3.first; i3<r3.second; ++i3 )
                            {
                                Type l2 = l3 - C[3]*i3;
                                std::pair<unsigned,unsigned> r2 = foo( 0, l2, 2, 21-i9-i8-i7-i6-i5-i4-i3 );
                                for( unsigned i2=r2.first; i2<r2.second; ++i2 )
                                {
                                    Type l1 = l2 - C[2]*i2;
                                    std::pair<unsigned,unsigned> r1 = foo( 0, l1, 1, 21-i9-i8-i7-i6-i5-i4-i3-i2 );
                                    for( unsigned i1=r1.first; i1<r1.second; ++i1 )
                                    {
                                        Type l0 = l1-C[1]*i1;
                                        Type val = maxval - l0;
                                        if( bar(val,i9,i8,i7,i6,i5,i4,i3,i2,i1) )
                                        {
                                            // 未必是从小到大排序
                                            std::cout << val << std::endl;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    return 0;
}

//449177399146038697307
//128468643043731391252
Are 2012-03-20
  • 打赏
  • 举报
回复
找到一个大神的算法,只需要2秒、我瞬间当机了!!!牛人啊!!!!!!
http://www.iteye.com/topic/763764
zhouyanligong 2011-05-15
  • 打赏
  • 举报
回复
这个很简单,但速度太慢了,求高手赐教!
zhouyanligong 2011-05-15
  • 打赏
  • 举报
回复
#include<iostream>
#include<cmath>
using namespace std;
void flower(long x,int n)
{
long z,y=x,sum=0;
while(x!=0)
{
z=x%10;
x=x/10;
sum=sum+pow(z,n);
}
if(y==sum)
cout<<y<<endl;
}
void main()
{
int len;
long value;
cout<<"input n value:"<<endl;
cin>>len;
for(value=pow(10,len-1);value<pow(10,len);value++)
{
flower(value,len);
}
}
liingfong 2011-05-13
  • 打赏
  • 举报
回复
33楼厉害
oiacm 2011-05-13
  • 打赏
  • 举报
回复
同求思路啊~~~有些人怎么写的,40秒就跑出来了
MR_Teen 2011-05-11
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 cx08030072 的回复:]

看来也是参加竞赛的兄弟啊!之前我还在笑话java组的,那么慢的语言解决这种需要效率的问题一定很纠结吧!可是现在我发现自己错了,java提供了很强大的功能,写起来简单多了,可以把精力集中在优化算法上。而我们C语言组的还得先想办法怎么存储和表示这个“21位数”...
[/Quote]

我准备用数组来,但是我估计了一下,怎么都非常之困难达到三分钟之内 能解决出来,求高手
_青v菜_ 2011-05-09
  • 打赏
  • 举报
回复


#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "time.h"
#define MAXN 22

typedef struct bignum
{
int digits[MAXN];
int lastdigit;
}BigNum;

BigNum pow21[10][MAXN];

int ansnum[10],sumnum[10];

BigNum bigpow(int a,int x);//计算0~9的任意次幂
BigNum bigadd(BigNum x,BigNum y);//返回x+y
BigNum bigmul(BigNum x,int y);//返回x*y
void disp(BigNum x);//输出一个BigNum

void check(BigNum sum);//检测
void dfs(int s,int remain,BigNum sum);
void search(int x);//求解函数
int main()
{
int t;
t=clock();
search(21);
printf("Time is:%d ms.\n\n",clock()-t);
/* BigNum x;
x=bigpow(8,21);
disp(x);
x=bigadd(x,x);
disp(x);
*/ return 0;
}
//0~9^x次方
BigNum bigpow(int a,int x)
{
BigNum mul;
int i,j,t,carry;
memset(&mul,0,sizeof(BigNum));
if(a==1){
mul.digits[0]=1;
mul.lastdigit=0;
}
else if(a>1){//a>1
mul.digits[0]=a;
mul.lastdigit=0;
for(i=1;i<x;i++){
carry=0;
for(j=0;j<=mul.lastdigit;j++){
t=mul.digits[j]*a+carry;
mul.digits[j]=t%10;
carry=t/10;
}
if(carry!=0)
{
mul.digits[++mul.lastdigit]=carry;
}
}
}
else{
printf("a<0");
}
return mul;
}

BigNum bigadd(BigNum x,BigNum y)
{
int i,t,carry;
BigNum sum;
memset(&sum,0,sizeof(sum));
sum.lastdigit=x.lastdigit>y.lastdigit?x.lastdigit:y.lastdigit;
carry=0;
for(i=0;i<=sum.lastdigit;i++)
{
t=x.digits[i]+y.digits[i]+carry;
sum.digits[i]=t%10;
carry=t/10;
}
if(carry!=0)
{
sum.digits[++sum.lastdigit]=carry;
}

return sum;
}

BigNum bigmul(BigNum x,int y)
{
int i,t,carry;
BigNum m;
memset(&m,0,sizeof(m));
m.lastdigit=x.lastdigit;
carry=0;
for(i=0;i<=x.lastdigit;i++)
{
t=x.digits[i]*y+carry;
m.digits[i]=t%10;
carry=t/10;
}
if(carry!=0)
{
m.digits[++m.lastdigit]=carry;
}
return m;
}

void check(BigNum sum)
{

if(sum.lastdigit!=20) return ;
int i=0;
memset(sumnum,0,sizeof(sumnum));
for(i=0;i<=sum.lastdigit;i++)
sumnum[sum.digits[i]]++;

for(i=9;i>=0;i--)
if(sumnum[i]!=ansnum[i]){
return;
}
disp(sum);
}

void disp(BigNum x)
{
int i;
for(i=x.lastdigit;i>=0;i--)
printf("%d",x.digits[i]);
printf("\n");
}


void dfs(int s,int remain,BigNum sum)
{

if(s==0){
ansnum[0]=remain;
check(sum);
memset(&sum,0,sizeof(sum));//清零
return;
}
BigNum newsum;
for(ansnum[s]=remain;ansnum[s]>=0;ansnum[s]--)
{
newsum=bigadd(sum,pow21[s][ansnum[s]]);
dfs(s-1,remain-ansnum[s],newsum);
}
}

void search(int x)
{
//初始化pow21
BigNum sum;
memset(pow21,0,sizeof(pow21));
int i,j;
for(i=1;i<10;i++)
pow21[i][1]=bigpow(i,x);
for(i=1;i<10;i++)
for(j=2;j<=x;j++)
pow21[i][j]=bigmul(pow21[i][1],j);

memset(&sum,0,sizeof(sum));
dfs(9,x,sum);
}

自己写的~~~结贴了
liuzhengxi2010 2011-05-06
  • 打赏
  • 举报
回复
不好写啊…算法的这个东西不好搞啊
neutroliza 2011-05-05
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 qiao496918166 的回复:]
#include <sstream>
#include <iostream>
#include <cstdlib>
#include <ctime>


using namespace std;

template<class T> string tostring(T a){ostringstream os;os<<a;return os.str();}

……
[/Quote]不能运行
qiaolixian 2011-05-03
  • 打赏
  • 举报
回复

#include <sstream>
#include <iostream>
#include <cstdlib>
#include <ctime>


using namespace std;

template<class T> string tostring(T a){ostringstream os;os<<a;return os.str();}

#define N 21

typedef pair<long long,long long> NUM;
#define MOD 1000000000000000LL;

NUM pow21[10][N+1];
int sump[10][N+1];

void init()
{
for(int i=0;i<10;i++)
for(int j=0;j<=N;j++)
sump[i][j]=i*j;

for(int i=0;i<10;i++)
{
pow21[i][0].first=pow21[i][0].second=0;
}
pow21[0][1].first=pow21[0][1].second=0;
for(int i=1;i<10;i++)
{
pow21[i][1].first=1;
pow21[i][1].second=0;
for(int j=0;j<N;j++)
{
pow21[i][1].first*=i;
pow21[i][1].second*=i;
pow21[i][1].second+=pow21[i][1].first/MOD;
pow21[i][1].first%=MOD;
}
}
for(int j=2;j<=N;j++)
{
for(int i=0;i<10;i++)
{
pow21[i][j].first=j*pow21[i][1].first;
pow21[i][j].second=j*pow21[i][1].second;
pow21[i][j].second+=pow21[i][j].first/MOD;
pow21[i][j].first%=MOD;
}
}
}

int numct[10],numct2[10];

void print(NUM t)
{

string s=tostring(t.first);
s=string(15-s.size(),'0')+s;
cout<<t.second<<s<<endl;
}


void check(NUM sum)
{
sum.second+=sum.first/MOD;
sum.first%=MOD;
if(sum.second<100000||sum.second>=1000000)return;
memset(numct2,0,sizeof(numct2));
long long t=sum.first;
for(int i=0;i<15;i++)
{
numct2[t%10]++;
t/=10;
}
t=sum.second;
for(int i=0;i<6;i++)
{
numct2[t%10]++;
t/=10;
}
if(memcmp(numct,numct2,sizeof(numct))==0)
print(sum);
}

void dfs(int k,int remain,NUM sum,int sum2)
{
if(k==2)
{
if((sum.first+sum.second-sum2)%9!=0)return;
}
if(k==0)
{
numct[0]=remain;
check(sum);
return;
}
NUM newsum;
for(numct[k]=remain;numct[k]>=0;numct[k]--)
{
newsum.first=sum.first+pow21[k][numct[k]].first;
newsum.second=sum.second+pow21[k][numct[k]].second;
dfs(k-1,remain-numct[k],newsum,sum2+sump[k][numct[k]]);
}
}

int main()
{
int cl=clock();
init();
dfs(9,N,pair<long long,long long>(),0);
cout<<"TIME::"<<clock()-cl<<"ms"<<endl;
cin>>cl;

return 0;
}

用F9,F10 单步执行,分析就行了。
chaoqingjiang 2011-05-03
  • 打赏
  • 举报
回复
package com.jcq;

import java.math.BigInteger;
import java.util.Hashtable;

public class Main {

private static final int SIZE = 21;
private int[] countArray = new int[10]; // 个数列表
private int[] countSumArray = new int[10]; // 个数总数
private BigInteger[] sumArray = new BigInteger[10];// 值总数
private int offset = 0;// 浮标

/**
* 设置当前浮标对应的个数,个数的总数,值总数
*
* @param num
* 个数
*/
private void setValue(int num) {
countArray[offset] = num;
if (offset == 0) {
countSumArray[offset] = num;
sumArray[offset] = p(9 - offset).multiply(n(num));
} else {
countSumArray[offset] = countSumArray[offset - 1] + num;
sumArray[offset] = sumArray[offset - 1].add(p(9 - offset).multiply(n(num)));
}
}

/**
* 检验当前数据是否匹配
*
* @return
*/
private boolean checkPersentArray() {
BigInteger minVal = sumArray[offset];// 当前已存在值
BigInteger maxVal = sumArray[offset].add(p(9 - offset).multiply(n(SIZE - countSumArray[offset])));// 当前已存在值+可能存在的最大值
// 最小值匹配
if (minVal.compareTo(MAX) > 0) {
return false;
}
// 最大值匹配
if (maxVal.compareTo(MIN) < 0) {
return false;
}
String minStr = minVal.compareTo(MIN) > 0 ? minVal.toString() : MIN.toString();
String maxStr = maxVal.compareTo(MAX) < 0 ? maxVal.toString() : MAX.toString();
// 找到最小值与最大值间首部相同的部分
int[] sameCountArray = new int[10];
for (int i = 0; i < SIZE; i++) {
char c;
if ((c = minStr.charAt(i)) == maxStr.charAt(i)) {
sameCountArray[c - '0'] = sameCountArray[c - '0'] + 1;
} else {
break;
}
}
// 判断如果相同部分有数据大于现在已记录的位数,返回false
for (int i = 0; i <= offset; i++) {
if (countArray[i] < sameCountArray[9 - i]) {
return false;
}
}
// 如果当前值的总数为SIZE位,那么判断该值是不是需要查找的值
if (countSumArray[offset] == SIZE) {
String sumStr = sumArray[offset].toString();
BigInteger sum = ZERO;
for (int i = 0; i < sumStr.length(); i++) {
sum = sum.add(p(sumStr.charAt(i) - '0'));
}
return sum.compareTo(sumArray[offset]) == 0;
}
return true;
}

/**
* 退出循环,打印
*
* @return
*/
private void success() {
System.out.println("find a match number:" + sumArray[offset]);
}

/**
* 将浮标指向下一位数
*
* @return
*/
private void next() {
offset++;
setValue(SIZE - countSumArray[offset - 1]);
}

/**
*
* 回退浮标,找到最近的浮标,并减一
*
* @return
*/
private boolean back() {
// 回退浮标,找到最近的浮标,并减一
if (countArray[offset] == 0) {
while (countArray[offset] == 0) {
if (offset > 0) {
offset--;
} else {
return true;
}
}
}
if (offset > 0) {
setValue(countArray[offset] - 1);
return false;
} else {
return true;
}
}

/**
* 测试程序
*
* @param startValue
* 测试匹配数中包含9的个数
* @param startTime
* 程序启动时间
*/
private void test(int startValue, long startTime) {
// 设置9的个数
offset = 0;
setValue(startValue);
while (true) {
if (checkPersentArray()) {// 检查当前提交数据是否匹配
// 匹配且总数正好为SIZE的位数,那么就是求解的值
if (countSumArray[offset] == SIZE) {
success();
}
// 总数不为SIZE,且当前值不在第10位(即不等于0)
if (offset != 9) {
next();
continue;
}
// 总数不为SIZE,且当前值在第10位。
if (back()) {
break;
}
} else {
if (back()) {
break;
}
}
}

System.out.println(Thread.currentThread() + " End,Spend time " + (System.currentTimeMillis() - startTime) / 1000 + "s");
}

/**
* 主函数
*/
public static void main(String[] args) {
final long startTime = System.currentTimeMillis();
int s = MAX.divide(p(9)).intValue();
for (int i = 0; i <= s; i++) {
// new Main().test(i, startTime);
// 启动十个线程同时运算
final int startValue = i;
new Thread(new Runnable() {

public void run() {
new Main().test(startValue, startTime);
}
}).start();
}
}
private static final BigInteger ZERO = new BigInteger("0");
private static final BigInteger MIN;
private static final BigInteger MAX;

/**
* 0-SIZE间的BigInteger
*/
private static final BigInteger n(int i) {
return (BigInteger) ht.get("n_" + i);
}

/**
* 0-9的次方的BigInteger
*/
private static final BigInteger p(int i) {
return (BigInteger) ht.get("p_" + i);
}
/**
* 用于缓存BigInteger数据,并初始化0-SIZE间的BigInteger和0-9的次方的BigInteger
*/
private static Hashtable<String, Object> ht = new Hashtable<String, Object>();

static {
int s = SIZE < 10 ? 10 : SIZE;
for (int i = 0; i <= s; i++) {
ht.put("n_" + i, new BigInteger(String.valueOf(i)));
}
for (int i = 0; i <= 10; i++) {
ht.put("p_" + i, new BigInteger(String.valueOf(i)).pow(SIZE));
}
MIN = n(10).pow(SIZE - 1);
MAX = n(10).pow(SIZE).subtract(n(1));
}
}
哎看不懂!
chaoqingjiang 2011-05-03
  • 打赏
  • 举报
回复
ri_aje 2011-05-02
  • 打赏
  • 举报
回复
根据水仙花数的定义,在正整数集中,只存在有限个水仙花数,而且已经完全已知,因此楼主可以通过查表得出结果,没必要自己重新计算。这里就有一张表,http://mathworld.wolfram.com/NarcissisticNumber.html,可以看到 N == 21 时,十进制下只有两个水仙花数。当然,楼主要是觉得这是作弊的话,就当我没说吧,只不过我觉得这就像使用圆周率一样,没必要还的自己发明个算法计算一下吧。
dc老师 2011-05-01
  • 打赏
  • 举报
回复
我写的,但是速度很慢,到7位的时候已经20s左右,如果到21位得几千万年...
/**
* 一个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分钟内运行完毕。
*/
package edu.excise.kaoshi;

import java.math.BigInteger;
import java.util.ArrayList;

public class Test10
{
public static final int SIZE = 24;

public static void main(String[] args)
{
MyStack myStack = new MyStack();
// String sStart = "10000000000";
// String sEnd = "99999999999";
String sStart = "1000000000";
String sEnd = "9999999999";
String mubiao;
int[] arr = new int[SIZE];
int[] sum = new int[SIZE];
int jieQu = 0;// 用来删除数组前n为零,以便与s比较
ArrayList list = new ArrayList();
BigInteger start = new BigInteger(sStart);
BigInteger end = new BigInteger(sEnd);
BigInteger ONE = new BigInteger("1");
for (BigInteger i = start; i.compareTo(end) < 0; i = i.add(ONE))
{
String s = i.toString();
mubiao = "";
// System.out.println(s + "的各项和为:");
// 入栈
for (int i1 = 0; i1 < s.length(); i1++)
{
myStack.push(s.charAt(i1));

}
// 出栈,进入数组
for (int i2 = myStack.index; i2 >= 0; i2--)
{
arr[SIZE - s.length() + i2] = myStack.pop();
}
// 求出次幂,并加入list,准备求加法
for (int i3 = 0; i3 < SIZE; i3++)
{
list.add(power(arr[i3], s.length()));
}
// 开始求和并且把list滞空,以便后面的数字调用
sum = getSum(list);
list.clear();
//获得求和后数组,并且截取前n为0,字符串
for (int i4 = 0; i4 < sum.length; i4++)
{
if (sum[i4] == 0)
{

} else
{
jieQu = i4;
break;
}
}
for (int i5 = jieQu; i5 < sum.length; i5++)
{
mubiao = mubiao + sum[i5];
}
//判断是否是花朵数
if (mubiao.equals(s))
{
System.out.println(s + "是一个花朵数字");
}
}
System.out.println("程序执行完毕");

}

public boolean isHuaDuoShu()
{
return false;
}

// 求21项的和
public static int[] getSum(ArrayList list)
{
int[] sum = new int[SIZE];
for (int i = 0; i < list.size(); i++)
{
sum = add(sum, (int[]) list.get(i));
// System.out.print("每次加完后的和为");
// for (int i5 = 0; i5 < sum.length; i5++)
// {
// System.out.print(sum[i5]);
// }
// System.out.println();
}
return sum;
}

// 每项的加法
public static int[] add(int sum[], int arr[])
{
int jinwei = 0;
for (int i = sum.length; i > sum.length - arr.length; i--)
{
int x = sum[i - 1] + arr[arr.length - sum.length + i - 1];
// 如果乘出的结果大于9,进位
if (x + jinwei > 9)
{
// 先用进位计算了本位结果之后,再赋给新的进位值
sum[i - 1] = (x + jinwei) % 10;
jinwei = (x + jinwei) / 10;
} else
{
sum[i - 1] = x + jinwei;
jinwei = 0;
}
}
return sum;
}

// 求幂次方
public static int[] power(int jishu, int zhishu)
{
int j = SIZE;// 数组大小
int jinwei = 0;// 防止相加的时机过早,加上这个参数
int[] arr = new int[j];// 数组
// for (int m = 0; m < SIZE; m++)
// arr[m] = 0;// 初始化
// 当指数为9时,刚传入,数组为空,先将最后一位赋值。
// i代表多少次方,j代表数组索引
for (int i = zhishu; i > 0; i--)
{
// 当第一次进入,复制
if (zhishu == i)
{
arr[j - 1] = jishu;

} else
{
// 进入循环,开始乘,遍历数组没一个元素
for (int p = SIZE; p > 0; p--)
{
// 每一位和基数乘后的值
int x = (arr[p - 1]) * jishu;
// 如果乘出的结果大于9,进位
if (x + jinwei > 9)
{
// 先用进位计算了本位结果之后,再赋给新的进位值
arr[p - 1] = (x + jinwei) % 10;
jinwei = (x + jinwei) / 10;

} else
{
arr[p - 1] = x + jinwei;
jinwei = 0;
}
}
}
}
return arr;
}

// 判断是否相等
public static boolean compareTo(int a[], int b[])
{
if (a.length == b.length)
{
for (int i = 0; i < a.length; i++)
{
if (a[i] != b[i])
{
return false;
}
}
} else
{
return false;
}
return true;
}
}

class MyStack
{
int[] arr = new int[Test10.SIZE];
int index = -1;
BigInteger num;

void push(char ch)
{
index++;
arr[index] = ch - 48;
}

int pop()
{
return arr[index--];
}

int getTop()
{
return arr[index];
}
}
cao_julians 2011-05-01
  • 打赏
  • 举报
回复
十进制数字只有十个,每一个数字的21次方不要重复计算,事先算一次存表。
任一21位整数拆分为21个数字后,查表比计算要节省很多时间
HaCool 2011-05-01
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 cx08030072 的回复:]
看来也是参加竞赛的兄弟啊!之前我还在笑话java组的,那么慢的语言解决这种需要效率的问题一定很纠结吧!可是现在我发现自己错了,java提供了很强大的功能,写起来简单多了,可以把精力集中在优化算法上。而我们C语言组的还得先想办法怎么存储和表示这个“21位数”...
[/Quote]
我还正再为怎么存这个数纠结呢
khzliu 2011-05-01
  • 打赏
  • 举报
回复
普通算法 求高效算法 ????????????????
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
void flower(int *,float,float,int);
void main()
{
time_t timep;
struct tm *p;
//---------开始时间--------------------
time(&timep); /*取得当地时间*/
p=localtime(&timep); /*转换时间*/
printf("开始时间:%d:%d\n" ,p->tm_min,p->tm_sec);
//------------------------------------------

int array[4]={0,0,0,0};//,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
float temp1=0,temp2=0;
int conter=1;
for(int i=1;i<10;i++)
{
array[0]=i;
flower(array,temp1,temp2,conter);
}
//----------------------------------------------
time(&timep); /*取得当地时间*/
p=localtime(&timep); /*转换时间*/
printf("\n结束时间 %d:%d\n",p->tm_min,p->tm_sec);
system("pause");
}

void flower(int *array,float temp1,float temp2,int conter)
{
conter++;
if(5==conter)
{
for(int n=0,m=4;n<4;n++,m--)
{
temp1+=pow(array[n],4);
temp2+=pow(10,m-1)*array[n];
}
if(temp2==temp1)
printf("%4.0f\n",temp1);
return;
}
for(int i=0;i<10;i++)
{
array[conter-1]=i;
flower(array,temp1,temp2,conter);
}
return;
}
aliuwr 2011-05-01
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 cx08030072 的回复:]

看来也是参加竞赛的兄弟啊!之前我还在笑话java组的,那么慢的语言解决这种需要效率的问题一定很纠结吧!可是现在我发现自己错了,java提供了很强大的功能,写起来简单多了,可以把精力集中在优化算法上。而我们C语言组的还得先想办法怎么存储和表示这个“21位数”...
[/Quote]
用字符数组存着,当然了,还要自己写加减函数
加载更多回复(20)

65,176

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧