回 帖 发 新 帖 刷新版面

主题:第72次比赛题目

[size=3]偶最近没有多少时间,只好偷一下懒了,用一题最近偶研究过的一个水题。。。

虽然的确挺水,但也想看看大家有什么方法优化

[color=0000FF]题目描述:[/color]
K进制的水仙花数定义:K进制下,一个大于一位的正整数,
各位上的数字的n次方的和,恰好等于它本身,找出所有的解

[color=0000FF]输入:[/color]
仅一行,分别为正整数n,k, 其中1<n<30,1<k<=36

[color=0000FF]输出:[/color]
输出所有的解,以k进制输出,一个解一行,10进制以上各位数值使用小写a-z表示

[color=0000FF]样例输入:[/color]
3 10

[color=0000FF]样例输出:[/color]
370
407
153
371

[color=0000FF]其它:[/color]
注意,输出结果不需要排序
结束时间,9月20日晚23:00

主要评比内容:正确性、时间效率、空间效率[/size]

回复列表 (共12个回复)

沙发

说真的,没有怎么读懂你的题目?
你说的意思是所有的数据吗?你定义的数据上限上多少呢?
你说的数据是不是在100---1000之内呢?
还是其它的呢?
我反正没有看到你的370.etc
是怎么样得出来的,为什么就只能是那几个数呢?
..........................
我想不可能就只有那么几个数是K进制水鲜花数呢.

板凳

#include<stdio.h>
#include<math.h>
main()
{
int base,exponet,buff[20]={0},lenow=1,num,p,sum,max=0;
char out[21];
printf("input the base and the exponet:");
scanf("%d%d",&base,&exponet);
num=buff[0]=base-1;
while(num++)
{
    buff[0]++;
    for(p=0;buff[p]>=base;)
    {
        buff[p]-=base;
        buff[++p]++;
    }
    max=(p+1)<=lenow?max:(lenow=p+1)*pow(base-1,exponet);
    if(max<=num)
        break;
    for(p=0,sum=0;p<=(lenow-1);p++)
        sum=sum+pow(buff[p],exponet);
    if(sum==num)
    {
        for(p=0;p<=lenow-1;p++)
        {
            if(buff[p]>=0&&buff[p]<=9)
                out[lenow-1-p]='0'+buff[p];
            else
                out[lenow-1-p]='A'+buff[p]-10;
        }
        out[lenow]='\0';
        printf("%s\n",out);
    }
}
getchar();
}



第一次在论坛发帖 希望大家多多支持 多多指点[em2]

3 楼

//没有好的办法,这个程序在大数据时肯定会溢出和超时!

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;

int a[10000];
inline long Power(int x,int n);     //求x的n次幂
long GetHighestPosition(int k,int n);    //求k进制下n次方可能达到的最高的位数
void GetShuiXianHuaNum(int n,int k,int t);    //在含有t位的数字组中,打印水仙花数

int main(){
 time_t start, finish;
 double duration;
 int i,n,k;
 cout<<"Please input n and k..."<<endl;
 cin>>n>>k;
 
 start = time(0);
 long p=GetHighestPosition(k,n);
 for (i=1; i<p; i++)//计算n位回归数 
 {
     GetShuiXianHuaNum(n,k,i);//计算n位回归数 
     cout<<endl;
 }
 finish = time(0);
 duration = difftime(finish, start);
 printf("\nProgram using time() = %f seconds.", duration);
 getchar();
 return 0;
}

inline long Power(int x,int n)
{
    if(n==1) return x;
    long p=Power(x,n>>2);
    if(n%2==1) return p*p*x;
    else return p*p;
}

long GetHighestPosition(int k,int n)
{
    long p=1;
    while(true){
        if(Power(k,p-1)>p*Power(k-1,n))
            break;
        p++;    
    }
    return p;
}

void GetShuiXianHuaNum(int n,int k,int t)
{
 int i;
 long max,min,m,sum;
 max=Power(k,t);
 min=max/10;
 
 a[n-1]=1;
 for(i=0;i<n-1;i++)
     a[i]=0;
     sum=1;
     for(m=min;m<max;m++)
     {
         if(sum==m) cout<<m<<"  "<<endl;
         for(i=0;i<n;i++)
         {
             sum-=Power(a[i],n);
             a[i]++;
             if(a[i]<k)
             {
                 sum+=Power(a[i],n);
                 break;
             }
             a[i]=0;
         }
     }
}

4 楼



不行!!上面的太慢,必须重写,我忘了iAkiak的关于大数运算的提醒了。

5 楼


include<iostream>
using namespace std;
void main()
{
    int i,j,n,k;long double s1,s2,s,t;long double p=1;
    int a[29]={0};s1=s2=s=t=0;
    cin>>n>>k;
    a[0]=1;
    for(i=0;i<n;++i)
      if(a[i]>0)
      { p=1;
        for(j=n-1;j>i;--j)  p=p*k;
        s1=s1+p*a[i];
      }
     for(i=0;i<n;++i)  a[i]=k-1;
     for(i=0;i<n;++i)
      if(a[i]>0)
      { p=1;
        for(j=n-1;j>i;--j)  p=p*k;
        s2=s2+p*a[i];
      }
     s=s1;int m=n-1; a[0]=1;for(i=1;i<n;++i)  a[i]=0;
     while(s<=s2)
     {
       a[m]=a[m]+1;t=0;s=0;
       for(i=0;i<n;++i) if(a[i]==k) { a[i]=a[i]-k;   a[i-1]=a[i-1]+1; }
       for(i=0;i<n;++i)  t=t+a[i]*a[i]*a[i];
       for(i=0;i<n;++i)
         if(a[i]>0)
         { p=1;
           for(j=n-1;j>i;--j)  p=p*k;
           s=s+p*a[i];
         }
         if(s==t) 
         {for(i=0;i<n;++i)          {if(a[i]<10)  cout<<a[i];
                                    if(a[i]==10) cout<<"a";
                                    if(a[i]==11) cout<<"b";
                                    if(a[i]==12) cout<<"c";
                                    if(a[i]==13) cout<<"d";
                                    if(a[i]==14) cout<<"e";
                                    if(a[i]==15) cout<<"f";
                                    if(a[i]==16) cout<<"g";
                                    if(a[i]==17) cout<<"h";
                                    if(a[i]==18) cout<<"i";
                                    if(a[i]==19) cout<<"j";
                                    if(a[i]==20) cout<<"k";
                                    if(a[i]==21) cout<<"l";
                                    if(a[i]==22) cout<<"m";
                                    if(a[i]==23) cout<<"n";
                                    if(a[i]==24) cout<<"o";
                                    if(a[i]==25) cout<<"p";
                                    if(a[i]==26) cout<<"q";
                                    if(a[i]==27) cout<<"r";
                                    if(a[i]==28) cout<<"s";
                                    if(a[i]==29) cout<<"t";
                                    if(a[i]==30) cout<<"u";
                                    if(a[i]==31) cout<<"v";
                                    if(a[i]==32) cout<<"w";
                                    if(a[i]==33) cout<<"x";
                                    if(a[i]==34) cout<<"y";
                                    if(a[i]==35) cout<<"z";}
                                    cout<<endl;
         }
     }
}

6 楼

#include<iostream>
using namespace std;
int Totallnum=0;
void PrintNumber(int Num,int K);
void Pcheck(int n,int k);

void main()
{
    int K=0;
    int N=0;
    while(1)
    {
        
    cout<<"请输入指数:"<<"范围:1<N<30"<<endl;
     cin>>N;
    cout<<"请输入输出进制形式:"<<"范围:1<K<=36"<<endl;
     cin>>K;

    Pcheck(N,K);
    }
}

void Pcheck(int n,int k)
{
    int i,j,m,h;
    int number;
    int sum,sum1=1,sum2=1,sum3=1;
    
    for(i=1;i<10;i++)
    {
        for(j=0;j<10;j++)
        {
            for(m=0;m<10;m++)
            {
                number=100*i+10*j+m;
                for(h=1;h<=n;h++)
                {
                    sum1=sum1*i;
                    sum2=sum2*j;
                    sum3=sum3*m;
                }
         
                sum=sum1+sum2+sum3;
                sum1=1;
                sum2=1;
                sum3=1;
                if(sum==number)
                {
                    Totallnum++;
                    PrintNumber(number,k);
                    cout<<"十进制数:"<<number<<endl;
                }
            }
        }
    }
    cout<<"满足这样进制的数总数为:"<<Totallnum<<endl;
     Totallnum=0;
}
                    
void PrintNumber(int Num,int K)
{
    
    int a[1000];
    int i,j;
    for(i=0;i<1000;i++)
    {
        a[i]=Num%K;
        Num=Num/K;
        if(Num==0)
            break;
    }
    cout<<K<<"进制数:";
    for(j=i;j>=0;j--)
        cout<<a[j];
        cout<<endl;
}

      

7 楼

新手上路,请多指教
[code=c]
#include <stdio.h>
#include <iostream.h>

//求解数a的n次方
long  ncifang(long a,int n)
{
    int i;
    long m=1;
    for (i=0;i<n;i++)
        m=m*a;
    return m;
}

//求一个数的最高次幂
int maxcifang(long n)
{
    int i=0;
    int j;
    for (j=10;n-j>=0;j=j*10)
        i++;
    return i;
}

//求出符合要求的数据
void qiujie(int n,int k)
{
    long data;
    
    for (data=10;data<ncifang(2,16);data++)
    {
        long end_data=0;
        int max;
        max=maxcifang(data);
        int a[10];
        int j=max;

        int temp;
        temp=data;
        for (int i=0;i<=max;i++)
        { 
            
            
            a[i]=temp/ncifang(k,j);
            temp=temp-a[i]*ncifang(k,j);
            j=j-1;
        }
        for (i=0; i<=max;i++)
          end_data=end_data+ncifang(a[i],n);
        
        if (end_data==data)
        cout<<data<<endl;
        
    }
    cout<<"ok!";
}

void main(void)
{
    int n;
    int k;
    cout<<"input n and k:"<<endl;
            cin>>n>>k;
    qiujie(n,k);
  }

[/code]

8 楼

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h> 
#include <limits.h>
#include <assert.h>
#include <conio.h>
#include <windows.h>
#include <algorithm>
#include <functional>
#include <stack>

#define        MAX_RADIX    37
#define        MAX_POWER    61
#define        MAX_SIZE    100    // 第0个结点用于存放数据的结点个数

int nPowerOfN[MAX_RADIX][MAX_POWER][MAX_SIZE];    // 

// dest[] = src[] * m
inline void MultiplyN(int dest[], int src[], int m, int radix)
{
    assert(m >= 0);
    if(m == 0)
    {
        dest[0] = 1;
        dest[1] = 0;
        return;
    }

    int            carry = 0;
    int            temp;

    dest[0] = src[0];
    for(int i=1; i<=src[0]; ++i)
    {
        temp    = src[i] * m + carry;
        carry   = temp / radix;
        dest[i] = temp - carry * radix;
    }
    while(carry > 0)
    {
        temp    = carry;
        carry    = temp / radix;
        dest[i++] = temp - carry * radix;
        ++dest[0];
    }
}

// dest[] = dest[] + src[]
inline void Add(int dest[], int src[], int radix)
{
    int        carry = 0;
    int        temp;
    int        len_d, len_s, min_len;

    len_s = src[0];
    len_d = dest[0];
    if(len_s > len_d)
    {
        min_len = len_d;
        dest[0] = len_s;
    }
    else
    {
        min_len = len_s;
        dest[0] = len_d;
    }

    for(int i=1; i<=min_len; ++i)
    {
        temp    = dest[i] + src[i] + carry;
        carry   = temp>=radix?1:0;
        dest[i] = temp - carry * radix;
    }
    for(; i<=len_s; ++i)
    {
        temp    = src[i] + carry;
        carry   = temp>=radix?1:0;
        dest[i] = temp - carry * radix;
    }
    for(; i<=len_d && carry>0; ++i)
    {
        temp    = dest[i] + carry;
        carry   = temp>=radix?1:0;
        dest[i] = temp - carry * radix;
    }
    if(carry > 0)
    {
        dest[i] = carry;
        ++dest[0];
    }
}

// dest[] = dest[] + m
void Add(int dest[], int m, int radix)
{
    int        carry = m;
    int        temp;

    for(int i=1; i<=dest[0] && carry > 0; ++i)
    {
        temp    = dest[i] + carry;
        carry   = temp>=radix?1:0;
        dest[i] = temp - carry * radix;
    }

    if(carry > 0)
    {
        dest[i] = carry;
        ++dest[0];
    }
}

// 预先求取某个进制下所有数字的各次幂的值
void Init(int n, int radix)
{
    int        i, j;

    for(j=0; j<=n; ++j)
    {
        nPowerOfN[0][j][0] = 1;
        nPowerOfN[1][j][0] = 1;
        nPowerOfN[1][j][1] = 1;
    }
    for(i=2; i<=radix; ++i)
    {
        nPowerOfN[i][0][0] = 1;
        nPowerOfN[i][0][1] = 1;
    }

    for(i=2; i<=radix; ++i)
    {
        for(j=1; j<=n; ++j)
        {
            MultiplyN(nPowerOfN[i][j], nPowerOfN[i][j-1], i, radix);
        }
    }
}

9 楼

// 输出水仙花数(如果非10进制,在在输出该进制的数值后,转换为10进制再次输出)
void Output(int sum[], int radix)
{
    for(int i=sum[0]; i>=1; --i)
    {
        if(sum[i] < 10)
            printf("%d", sum[i]);
        else
            printf("%C", 'a'+sum[i]-10);
    }
    printf("\n");
}

// 检查sum[]中存放的是否水仙花数
inline bool CheckNarcissus(int sum[], int n, int end, int radix, int k[])
{
    int            i;
    int            count[MAX_RADIX];
    
    if(sum[0] < n || k[sum[1]] == 0)
        return false;
    
    memset(count, 0, sizeof(int)*radix);
    for(i=1; i<=sum[0]; ++i)
        ++count[sum[i]];
    
    for(i=radix-1; i>end; --i)
        if(count[i] != k[i])
            return false;

    return true;
}

// 求水仙花数
inline void Narcissus(int sum[], int n, int left, int start, int radix, int k[])
{
    if(left == 0)
    {
        if(CheckNarcissus(sum, n, start, radix, k))
        {
            Output(sum, radix);
        }
        
        return;
    }
    
    int        tmp[MAX_SIZE];

    memcpy(tmp, sum, sizeof(int)*(sum[0]+1));
    if(start == 1)
    {
        k[0] = left;
        Narcissus(tmp, n, 0, start-2, radix, k);
            
        for(int i=1; i<=left; ++i)
        {
            k[start] = i;
            k[0] = left - i;
            Add(tmp, 1, radix);
            Narcissus(tmp, n, 0, start-2, radix, k);
        }
    }
    else
    {
        Narcissus(tmp, n, left, start-1, radix, k);
        
        for(int i=1; i<=left; ++i)
        {
            k[start] = i;
            Add(tmp, nPowerOfN[start][n], radix);
            Narcissus(tmp, n, left-i, start-1, radix, k);
        }
    }
    k[start] = 0;
}

int main()
{
    int            n, radix;
    int            k[MAX_RADIX]  = {0};
    int            sum[MAX_SIZE] = {1,0};

    while(scanf("%d%d", &n, &radix) == 2)
    {
        memset(sum, 0, sizeof(int)*MAX_SIZE);
        sum[0] = 1;

        Init(n, radix);
        Narcissus(sum, n, n, radix-1, radix, k);
        printf("\n");
    }

    return 0;
}

10 楼

另写了一个优化的程序,可惜对n<=30提升只有15%左右,而代码却长得很多。但对于n>39速度能提升1倍左右。

我来回复

您尚未登录,请登录后再回复。点此登录或注册