寻找“同构数”答案★★★★
“同构数”,又称为“自守数”。这又是一个著明的数学命题。
所谓“同构数”、“自守数”是指一个数的平方的尾数等于该数自身的自然数。例如:
0^2 = 0
1^2 =1
5^2 =25
6^2 =36
25^2 =625
76^2 =5776
由于需要计算准确的平方数,还要检查尾数和平方数的末位是否相同,当然有一定的难度。
第一级难度:用LOGO语言常规的计算方式可以求出0~9999之间的自守数。
这个问题可以简化成这样:假如原来这个数是2位数,那么我们只要求出平方值的最后两位数就行了。如果尾数等于原数,那么这个数就是自守数。计算表明,不大于10000的数中有9个自守数。
0 1 5 6 25 76 376 625
9376
这个程序请参考林老师编著的《LOGO语言竞赛习题集》P241,程序总共才有简单的9行。
第二级难度:用LOGO语言数组计算方式可以求出0~999999(甚至更大)的自守数。
但是上面这种编程方式显然有着极大的局限性:因为计算更大的平方数,LOGO系统必定会将得到的结果作为“科学计数法”进行处理,要想得到精确的数值就完全不可能了。所以历来求解的答案都没有超过9376、109376的,而且根本无法求出精确的平方值。
其实LOGO语言具有巨大的潜力。如果希望求解更高位数的自守数,必须引进数组,全面实行高精度计算。在下面的程序中只搜索到999999六位数。但是这个程序只要进行少量修改,实际上可以扩充到更高的数位。当然,这将要耗费更多的计算机运算时间。编程思路如下:
① 0是自守数,根本无需计算。直接纳入答案。
②
用FOR循环搜索1~999999(或更多的数位)。把平方数放在数组:A、:B中,把平方的结果放在数组:C中。先逐位把:A和:B相乘,结果存入:C中,然后处理平方乘法中的进位。
③
如果进行平方计算的数字的位数是:WS位,那么就对数组:A和数组:C的低:WS位进行比对,如果全部相同,显然是找到了自守数。这时就要显示找到的结果,并统计答案的个数。
数位比较长的“同构数”末尾与376、635密切关联,是否是规律,有待深入探讨。
TGS
0^2 = 0
1^2 =1
5^2 =25
6^2 =36
25^2 =625
76^2 =5776
376^2 =141376
625^2 =390625
9376^2 =87909376
90625^2 =8212890625
109376^2 =11963109376
890625^2 =793212890625
答案的总组数 =12
开始计算时间 11
46 10
计算结束时间 12
26 43
整个计算过程用了2433秒
TO TGS
;寻找同构数(自守数)
TS
;建立全文本显示方式
MAKE
"TI1
TIME
;检测开始计算时分秒
MAKE
"TTI1 (ITEM 1 :TI1)*3600+(ITEM 2 :TI1)*60+(ITEM 3 :TI1)
MAKE "A
BYTEARRAY 7
;建立放置等待进行平方计算的数的空间
MAKE "B
BYTEARRAY 7
MAKE "C
BYTEARRAY 13 ;建立存放平方值的空间
MAKE "N
1
;共有几个答案的存储空间
MAKE "WS
0
;存储待检同构数的数位
PR[0^2=0]
;输出第一个同构数
;=================在以下范围中寻找答案==================
FOR "T 1
999999[MAKE "TT :T FJ CF]
TYPE[答案的总组数= ]PR :N
;---------输出计算的时间----------
MAKE
"TI2
TIME
;检测计算结束时分秒
MAKE
"TTI2 (ITEM 1 :TI2)*3600+(ITEM 2 :TI2)*60+(ITEM 3 :TI2)
PR[] (PR
"开始计算时间 :TI1)
(PR
"计算结束时间 :TI2)
MAKE
"TTI3 :TTI2-:TTI1
(TYPE
"整个计算过程用了:) TYPE :TTI3 PR "秒
END
TO FJ
;先把5位数按位进行分解
;=============所有的存储空间清零================
FOR "I 1
6[ASET :A :I 0]
FOR "I 1
6[ASET :B :I 0]
FOR "I 1
12[ASET :C :I 0]
;=============把分解出来的数位存入数组==========
MAKE "WS
COUNT :TT ;检测是几位数
FOR "I 1
:WS[MAKE "T2 INT(:TT/10) MAKE "R :TT-:T2*10 \
ASET :A :I :R ASET :B :I :R MAKE "TT :T2]
END
TO CF
;进行平方乘法的计算
;********非常关键而且是难度最高的平方计算*******
FOR "I 1
:WS[FOR "J 1 :WS[ASET :C (:I+:J-1) \
(AGET :C (:I+:J-1))+((AGET :A :I)*(AGET :B :J))]\
FOR "K 1 (:WS+:WS)[IF (AGET :C :K)>9
THEN[\
MAKE "ZC INT((AGET :C :K)/10) \
ASET :C (:K+1) ((AGET :C (:K+1))+:ZC) \
ASET :C :K ((AGET :C :K)-:ZC*10) ]]]
;============检测是否同构程序段=================
MAKE "BZ
0 ;先假设已经构成同构数
FOR "I 1
:WS[IF (AGET :A :I)=(AGET :C :I) THEN[]ELSE[MAKE "BZ 1]]
MAKE
"FLAG 0
IF :BZ=0
THEN[(FOR "J 1 :WS[TYPE AGET :A (:WS-:J+1)]) TYPE[^2= ]
\
(FOR "JJ 1 12[MAKE "SHU (AGET :C 13-:JJ) \
(IF :SHU>0 THEN[MAKE "FLAG 1]) \
(IF :FLAG=1 THEN[TYPE :SHU])]) PR[]MAKE "N :N+1]
END
关于使用程序换行转接号“\”的技巧请参考:
重新塑造LOGO编程风格的程序换行转接号“\”