关于回文数的问题: (100分)

F

franczx

Unregistered / Unconfirmed
GUEST, unregistred user!
若一个数(首位不为0)从左到右读与从右到左读都是一样,这个数就叫做回文数,例如
12512就是一个回文数。
给定一个10进制正整数,把它的各位数字上数字倒过来排列组成一个新数,然后与原
数相加,如果是回文数则停止,如果不是,则重复这个操作,直到和为回文数为止。例如:10进制87则有:
STEP1: 87+78=165
STEP2: 165+561=726
STEP3: 726+627=1353
STEP4: 1353+3531=4884
编写一个程序,输入M(M最多20位),输出最少经过几步可以得到回文数。如果在30步以内
(含30步)不可能得到回文数,则输出“Impossible!”。数出格式为:
输入:M=87
输出:Step=6 ,4884
其实这个题很简单,但是问题是:要用优化算法,使程序的时间和空间复杂度尽量的小,
不知各位大虾有什么建议!比如说:用String或数组存储大整数啊,或者其他的算法,哪
怕是一点点,希望大家不吝赐教!当然,建议越多越好!谢谢了!不够的话我加分!!![8D]
 
这个不是好好的吗?
 
TO creation-zy:
老兄,你误解我的意思了。
不过我想你还是用了不少时间,谢谢了。
但是,我并不需要你的程序,程序我自己会编啊!我需要的是建议,想法!
谢!
 
>>用了不少时间
没有,才一个小时不到,小意思。
>>要用优化算法,使程序的时间和空间复杂度尽量的小
我已经做到了呀。请看 procedure TBigCycleNum.AddSelfReverse;
将数据存放在一个byte数组中,每个byte表示一位(0..9)。针对数组高速执行特定的计算。
>>建议,想法
如果你读懂了程序,就什么都有了。
 
摆平了! :)
type
TBigCycleNum=class
private
FNumBuf:array of Byte;
FCurLength,FCapcity:Integer;
function GetValue: String;
procedure SetValue(const Value: String);
procedure SetCapacity(const Value: Integer);
public
property Value:String read GetValue write SetValue;
property CurLength:Integer read FCurLength;
property Capacity:Integer read FCapcity write SetCapacity;
procedure AddSelfReverse;
function IsCycleNum:Boolean;
constructor Create;
destructor Destroy;
override;
end;

{ TBigCycleNum }
procedure TBigCycleNum.AddSelfReverse;
var
i,m:Integer;
begin
FNumBuf[FCurLength]:=0;
//最高位置零
for i:=0 to (FCurLength-1) div 2do
begin
FNumBuf:=FNumBuf+FNumBuf[FCurLength-1-i];
FNumBuf[FCurLength-1-i]:=FNumBuf;
end;
for i:=0 to FCurLength-1do
begin
m:=FNumBuf;
FNumBuf:=m mod 10;
FNumBuf[i+1]:=FNumBuf[i+1]+m div 10;
end;
if FNumBuf[FCurLength]>0 then
Inc(FCurLength);
end;

constructor TBigCycleNum.Create;
begin
SetLength(FNumBuf,0);
FCurLength:=0;
FCapcity:=0;
end;

destructor TBigCycleNum.Destroy;
begin
SetLength(FNumBuf,0);
inherited;
end;

function TBigCycleNum.GetValue: String;
var
i:Integer;
begin
SetLength(Result,FCurLength);
for i:=FCurLengthdo
wnto 1do
Result:=Char(Byte('0')+FNumBuf[FCurLength-i]);
end;

function TBigCycleNum.IsCycleNum:Boolean;
var
i:Integer;
begin
Result:=true;
for i:=0 to FCurLength div 2do
if FNumBuf<>FNumBuf[FCurLength-i-1] then
begin
Result:=false;
break;
end;
end;

procedure TBigCycleNum.SetCapacity(const Value: Integer);
begin
FCapcity:=Value;
SetLength(FNumBuf,Value);
end;

procedure TBigCycleNum.SetValue(const Value: String);
var
i:integer;
begin
FCurLength:=Length(Value);
if FCurLength>FCapcity then
SetCapacity(FCurLength);
for i:=0 to FCurLength-1do
FNumBuf:=Byte(Value[FCurLength-i])-Byte('0');
end;

function FindCycleNum(NumStr:String;var Times:Integer):String;
begin
Result:='';
Times:=0;
Form1.Memo1.Text:='';
with TBigCycleNum.Createdo
begin
Capacity:=Length(NumStr)+30;
//做30次加法最多增长30位
Value:=NumStr;
Times:=0;
repeat
Form1.Memo1.Lines.Add(Value);
if IsCycleNum then
begin
Result:=Value;
break;
end;
Inc(Times);
AddSelfReverse;
until Times>30;
if Times>30 then
Times:=-1;
//失败
Free;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
n:Integer;
begin
Caption:=FindCycleNum(Edit1.Text,n)+' '+IntToStr(n);
end;

eg: 967761 毫秒级搞定! (刚好30步)
967761
1135530
1490841
...
14003123453223003
44035358885353044

满意否? :)
 
嗬嗬,老兄,你没明白我的意思或者是我没有说清楚。程序我当然会,但是我想力求完美。
我一直在想是否有更简单的方法。
但是没有想到,其实程序我早就写好了。不过是用c写的,但并不是很满意。所以才求救
与大家。
源程序如下:
#define MaxN 40
#define MaxT 30
#include "string.h"
#include "math.h"
#include "stdio.h"
main()
{
void inputstr(char a[]);
int AddOnce(char a[]);
int judge(char a[],int arr);
void outputresult(int t,int tf,char a[]);
int times,bf,carry;
char str[MaxN];
times=0;bf=0;
inputstr(str);
if((judge(str,1)==1))
{
outputresult(0,1,str);
return;
}
for(times=1;times<=MaxT;times++)
{
carry=AddOnce(str);
if(judge(str,carry)==1)break;
}
if(times>=MaxT)times=MaxT;
bf=judge(str,1);
outputresult(times,bf,str);
}
void inputstr(char a[])
{ int i,inputerror;
printf("Please input a number between 1 and 1E20):");
do
{
inputerror=0;
scanf("%s",a);
for(i=0;i<=strlen(a)-1;i++)
{
if(a<'0'||a>'9')
{
inputerror=1;
for(i=0;i<=MaxN-1;i++)a='/0';
printf("Input Error.Try again:");
break;
}else
if(a[0]=='0')
{
printf("Input Error.Try again:");
inputerror=1;
}
if(inputerror==1)break;
}
} while(inputerror==1);
}

int AddOnce(char a[])
{ int i,length,car;
length=strlen(a);
car=0;
for(i=0;i<=(length-1)/2;i++)
{
a=a+a[length-1-i]-'0';
if(a>'9')car=1;
}
for(i=0;i<=(length-1)/2;i++)
a[length-1-i]=a;
/*gui zheng chang zheng shu*/
if(car==0)return(car);
a[length]='0';
for(i=0;i<=length-1;i++)
{
if(a>'9')
{
a-=10;
a[i+1]+=1;
}
}
if(a[length]=='0')a[length]='/0';
a[length+1]='/0';
return(car);
}

int judge(char a[],int car)
{
int length,i,mid;
length=strlen(a);
if(length<3)return(0);
if(car==0)return(1);
for(i=0;i<=(length-1)/2;i++)
{
mid=length-1-i;
if(a!=a[mid])return(0);
}
return(1);
}
void outputresult(int times,int bf,char a[])
{ int i,length;
length=strlen(a);
if(bf==1)
{
printf("Times:%d/nPalindrome Number:",times);
for(i=length-1;i>=0;i--)printf("%c",a);
printf("/n");
}else
printf("No Palindrome Number!/n");
}
运行:
Please input a number between 1 and 1E20):9987064
Times:29
Palindrome Number:1156661378731666511
不过呢,还是感谢了,浪费了你宝贵的时间,谢谢!
 
多人接受答案了。
 
顶部