这天正感无趣,树杈(一哥们儿)发来一个妖题,Google了一下,发现自己孤陋了。随手回了个话,建议他写个程序算算看。几天后见面时,那厮果然写程序算了,据说程序跑了一个下午没有把结果搞出来。听说另外还有一玩VB的兄弟算到程序崩溃也没看到答案。遂兴趣大起,和树杈一下探讨了一下算法,下面是一个效率尚可的解决办法,更高效算法尚在思考中(只是树杈在思考,我已经放弃动脑了,好累啊)。
#!/usr/bin/python2
#coding: utf83
'''4
Created on 2009-6-15
@author: sutra6

7
求满足下列条件的数:8
1、它是一个质数;9
2、它的各位数字必须是递减的;10
3、把它的数字逆转过来,得到各位递增的数字,仍然是个质数;11
4、它是满足以上三个条件的数字中最大的一个。12
'''13

14
'''15
删除数位求解法16
'''17
import string18
import math19

20
# 判断一个数是否是素数21
def isprime(prime):22
i=223
limit=int(math.sqrt(prime))24
for i in range(2,limit+1):25
if prime % i == 0:26
return False27
i=i+128
return True29

30
# 从数 a 中删除一位。31
def delete(a, arr):32
s = str(a)33
l = len(s)34

35
for j in range(0, l):36
b = (a / (10 ** (j + 1)) * (10 ** j)) + (a - a / (10 ** j) * (10 ** j))37
arr.append(b)38

39
if __name__ == '__main__':40
# 素数末位不能是0,并且又要递减,所以这里没有041
a = 98765432142
fromarr = [a]43
toarr = [a]44
result = []45

46
l = len(str(a))47

48
for i in range(1, l):49
for a in fromarr:50
delete(a, toarr)51
result.extend(toarr)52
fromarr = list(set(toarr))53

54
result = list(set(result))55
result.sort()56
#print result57

58
prime = []59
for b in result:60
if isprime(b) and isprime(int(str(b)[::-1])):61
prime.append(b)62

63
prime.sort()64
print prime[len(prime) - 1]65

思路比较简单:
1、因为是一个从高位到低位递减的数字,所以最大的一个符合条件的数字是9876543210。
2、以零结尾的数不可能是质数, 所以最大就变成了987654321,一共9位。
3、由于在一个顺序序列中任意删除一个或多个单元,该序列仍然有序,所以我们采用删位的方法来循环。(其实这里应该写个递归,树杈这人太懒了,懒的都快和我看齐了)
4、先看9位的数是否符合要求,如果不符合就从低位到高位穷举删掉1位的状况,看看有没有符合的,如果还没有就在删掉1位的数字的基础上再删掉1位……(明显就是递归嘛)
5、第一个遇到的符合条件的数字就是最大的符合条件的数,答案就是9875321,这个不包含任何政治意义的数字。
这里仅仅解释一下36行那个表达式,这个可读性极低的表达式绝对是偷懒的结果。
其实就像注释所说,希望从一个数字中删掉其中的某1位得到另一个数,我们觉得数学运算应该要比字符串运算要更快,所以写了这个表达式。
其原理很简单,假设要抽调十位上的数字,就把百位以上的数字用整除除出来然后乘以10再加上各位的数字就成了。
今天听说有一个可以提高质数检查效率的算法,持续关注中。

浙公网安备 33010602011771号