主题:第72次比赛题目
雨中飞燕
[专家分:18980] 发布于 2008-09-12 13:54:00
[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]
最后更新于:2008-09-12 13:55:00
回复列表 (共12个回复)
沙发
twwwater [专家分:10] 发布于 2008-09-15 12:58:00
说真的,没有怎么读懂你的题目?
你说的意思是所有的数据吗?你定义的数据上限上多少呢?
你说的数据是不是在100---1000之内呢?
还是其它的呢?
我反正没有看到你的370.etc
是怎么样得出来的,为什么就只能是那几个数呢?
..........................
我想不可能就只有那么几个数是K进制水鲜花数呢.
板凳
zerone [专家分:0] 发布于 2008-09-16 19:34:00
#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 楼
JackieRasy [专家分:3050] 发布于 2008-09-17 23:45:00
//没有好的办法,这个程序在大数据时肯定会溢出和超时!
#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 楼
JackieRasy [专家分:3050] 发布于 2008-09-18 14:58:00
不行!!上面的太慢,必须重写,我忘了iAkiak的关于大数运算的提醒了。
5 楼
天空飞雪 [专家分:960] 发布于 2008-09-19 07:46:00
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 楼
strugglemyself [专家分:100] 发布于 2008-09-20 12:57:00
#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 楼
zhangyuke [专家分:0] 发布于 2008-09-20 17:10:00
新手上路,请多指教
[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 楼
boxertony [专家分:23030] 发布于 2008-09-20 21:42:00
#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 楼
boxertony [专家分:23030] 发布于 2008-09-20 21:42:00
// 输出水仙花数(如果非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 楼
boxertony [专家分:23030] 发布于 2008-09-20 21:46:00
另写了一个优化的程序,可惜对n<=30提升只有15%左右,而代码却长得很多。但对于n>39速度能提升1倍左右。
我来回复