鱼C论坛

 找回密码
 立即注册
查看: 3964|回复: 14

[技术交流] 小练习:20161017 最大的n位pandigital质数是多少?

[复制链接]
发表于 2016-10-17 10:00:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 冬雪雪冬 于 2016-10-24 09:59 编辑

从现在开始我们要开展一批欧拉计划的习题练习。
其实在我们论坛中已有欧拉计划的板块,可能有些鱼油还没注意到。
什么是欧拉计划:http://bbs.fishc.com/thread-60405-1-1.html
我们欧拉板块现已给出了81道题,这批练习将从欧拉计划中选题。其实用python语言完成有很多的优势,可以更简洁更方便的实现。
如果大家有兴趣也可浏览欧拉的英文网站:https://projecteuler.net/archives
这里已经有了500余题。


                               
登录/注册后可看大图

好了言归正传,我们开始做小练习。




题目要求:
以python语言完成,如果是python2请注明。
程序以代码文字格式发帖。
注重程序效率和创意。
答题在一周内完成,即10.24 10:00之前,其后将公开大家的答案,并评比成绩。

另程序和答案可以在网上搜到,希望大家独立完成。

----回帖需写明解题思路,鼓励在程序中加上注释-----
----除列出程序外,请给出输出的结果。----



题目:

如果一个数字将 1 到 n 的每个数字都使用且只使用了一次,我们将其称其为一个 n 位的 pandigital 数。例如,2143 是一个 4 位的 pandigital 数,并且是一个质数。

最大的 n 位 pandigital 质数是多少?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-10-17 11:05:00 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2016-10-17 14:02 编辑

这题其实有好多解法,我也想正好借这题,分享一些使用python解决一些数学题的心得。
【版主,在比赛结束后,如果觉得这篇经验分享还实用的话,希望能申请精华,让更多的鱼油看到,毕竟也花了我好些时间写的!@小甲鱼 @冬雪雪冬 】
主要是针对没有任何算法基础的鱼油,算法高手可以直接跳过。

首先,从解题思路开始吧:
1. 最简单粗暴的方法,当然是暴力解法,就是从1开始依次往上增加,最大值当然是987654321,因为超过这个值就没法构成Pandigital了。
        a)用暴力解法获取候选数
        b)有了候选数以后就依次判断每个数,是否是Pandigital
                i) 候选数判断法:判断方法其实很简单,只要候选数中从1~n没有重复的数字即是Pandigital (举例:可以利用函数set()函数及len()把候选数列化为元组,再判断元组长度是否与原来相同,如果有重复的,长度必然会不同。)
                ii)Pandigital直接生成法:直接生成的Pandigital数列可以省去判断的步骤,节省计算时间,后面介绍
        c)有了Pandigital数以后就要判断是否是质数(质数的定义是:除了可以被1和自己本身整除以外,不能被其他自然数整除的数)
              质数的判断方法也有很多:
                i) 暴力解法,同样使用从2开始的(1可以不用尝试,因为任何自然数必然能被1整除)自然数依次与候选数相除,上限是比本身小1的整数。如果中间没有任何一个数能与之整除,则即是质数,不然就不是(不是质数的自然数就是合数(除1以外))。
                ii) 优化算法1: 候选数范围优化,后面介绍
                iii)优化算法2: 表格标记法优化,后面介绍
                iv)其他优化算法: 后面介绍
        d)判断完质数以后,如果是质数,则保存起来后续要比较大小,如果不是则废弃。
                比较大小其实也有不同的方法,而且所用时间也各不相同。
                i) 函数法:直接用max()或min()函数,求最大最小值。优点:简单,但如果候选数非常多的话,速度也不快(因为它的原理也是依次比较,然后判断)
                ii)标记法:直接在计算过程中标记出最大值或最小值,这样只要计算完最大或最小值就出来了,不用额外计算时间。
                iii)后排序法:用sort()或者sorted()对运算的结果排序后,那么第一个或者最后一个就是最大最小值。
                iv)前排序法:用sort()或者sorted()对运算之前的候选数排序,那么这样只要在运行过程中第一个满足运算条件的数,就是要找的最大或最小值,后面的其他候选数都不用计算了。
        做完,这么多步骤以后,我们终于得到我们需要的答案了。
2. 当然,你完全可以按照(1.)中描述的暴力解法的思路进行解题,而且只要思路正确,有足够时间,肯定能计算出结果。
    但是,我要说的当然远不是这样。如果全部用上述的暴力解法解这题估计得花上几天(说不定几周)的时间来运行程序,这当然不是我们所希望的。
    那么,我们就需要对上述的暴力解法进行优化了。(其实上述暴力解法的每个步骤都可以优化,我会逐步说明。)
        a)候选数的优化
                要判断候选数是不是Pandigital,最快的方法,当然是直接生成Pandigital啦,这样根本都不需要判断
                所以,我用了Pandigital的生成法。生成法也有不同的方式,我写了2种不同的方案。
                第一种是利用python的itertools库的函数permutations,生成排列组合。优点是程序简单。
  1. from itertools import permutations as per
  2. def getPan1(n):
  3.         pan = per(range(1,n+1),n)
  4.         panlist = []
  5.         for each in pan:
  6.             ee = 0
  7.             for e in each:
  8.                 ee = ee*10 + e
  9.             panlist.append(ee)
  10.         return panlist
复制代码

                第二种是用插入法,自己写的生成程序,运用了递归算法。
  1. def getPan2(n):
  2.         if n == 2:
  3.                 return [12,21]
  4.         if n>2:
  5.                 pan = getPan2(n-1)
  6.                 length = len(str(pan[0]))
  7.                 pannew = []
  8.                 for each in pan:
  9.                         pannew.append(int(str(n)+str(each)))
  10.                         pannew.append(int(str(each)+str(n)))
  11.                         for j in range(1,length):
  12.                                 pannew.append(int(str(each)[:j]+str(n)+str(each)[j:]))
  13.                 return pannew
复制代码

                两种算法各有利弊,对于本题来说,差异并不是太明显,但是对于大数量的排序的话,差异会越来越明显。
        b)质数判断优化
                有了候选数以后就要判断质数了。
                i)候选数的范围优化
                        其实,我们不需要把每个候选数都拿去和比候选数小的自然数相除来判断是否是质数。
                        质数有几个特性:
                        > 除了2以外,能被2整除的都不是质数(废话)。这样就可以砍掉一半的候选数了。
                        > 除了2和3以外的质数必然符合6k+/-1(k为自然数),这样又减少了1/6的数量。
                        > 而在相除时,只需相除到n**0.5(即根号n)即可,不需要全部除到完,这样再减少3/4的工作量。
  1. def isPrime1(num):
  2.         if num == 2 or num ==3:
  3.                 return True
  4.         elif num%2 == 0:
  5.                 return False
  6.         elif (num-1) % 6 != 0 and (num+1) % 6 != 0:
  7.                 return False
  8.         else:
  9.                 for i in range(3,int(num**0.5+1),2):
  10.                         if num%i == 0:
  11.                                 return False
  12.                 return True
复制代码

                ii)表格标记法优化
                        这种方法是先建立一个“空”的表格,然后依次把可能的项填入,或把不可能的项移除。标记法往往可以和递归算法套用,运用递归算法的便捷,加上标记法的高效记录。(纯用递归算法的话,往往效率很低,特别是嵌套层数很深的情况。)
                        在这里例子中,我是先建立了一个全为True的表格,然后依次把能除净的数(还包括0和1)对应的空格标记为False,那么剩下的就都是质数了。表格的index和表格的值,可以用enumerate()函数联系起来。另外,表格的范围也只需到n**0.5的大小即可。
  1. def getPrime(n):
  2.     primes = [True]*n
  3.     primes[0], primes[1] = False, False
  4.     for (i, prime) in enumerate(primes):
  5.         if prime:
  6.             for j in range(i*i,n,i):
  7.                 primes[j] = False
  8.     primelist = []
  9.     for (k, trueprime) in enumerate(primes):
  10.         if trueprime:
  11.             primelist.append(k)
  12.     return primelist

  13. primes = getPrime(10001)
  14. def isPrime2(num):
  15.     if num in primes :
  16.         return True
  17.     elif (num-1) % 6 != 0 and (num+1) % 6 != 0:
  18.         return False
  19.     else:
  20.         for eachprime in primes:
  21.             if num % eachprime == 0:
  22.                 return False
  23.         return True
复制代码

                iii)其他算法优化
                        其实,上述的优化算法都可以相互结合,取长补短,根据不同的情况灵活调用。
                通过这些性质的优化后,所剩的候选数已经足够可以被我们日常的计算机所应付了。
        c) 比较大小数的优化
                在取得了是质数并且是Pandigital的数以后,最后一步就是取得这些值中的最大值
                上面提的的函数法、标记法和后排序法,其实都是属于后运算的算法。这些算法都是要运算并且比较所有的候选数。
                那么,有没有前运算的算法呢? 答案是有的,前排序法就是前运算的算法。
                这种算法的好处是,一旦得到第一个符合条件的值以后,后续的数值就不需要再运算了,可以节省大量时间。同时也省去了保存候选数的麻烦,因为根本都不需要保存。
                方法就是:用sort(),reverse()或者sorted(),reversed()对运算之前的候选数排序,那么这样只要在运行过程中第一个满足运算条件的数,就是要找的最大或最小值,后面的其他候选数都不用计算了。
  1. for k in range(9,1,-1):
  2.         testpan = reversed(getPan1(k))
  3.         for eachpan in testpan:
  4.                 if isPrime1(eachpan):
  5.                     print (eachpan)
  6.                     end = time()
  7.                     print ('Use: %.3f sec.' % (end-start))
  8.                     exit()
复制代码

3. 结果
  1. 7652413
  2. Use: 0.405 sec.
复制代码

        这个就是运行的结果,我使用的是getPan1()及isPrime1()的方法。大家可以自行调试不同方法的差异。基本上这几种方法都是很快速的,都可以控制在0.5秒以内完成。这样,我们就把一个程序从原本可能要运行几天的时间,缩短到毫秒级的单位,这都是算法的功劳。
源代码如下:
  1. from itertools import permutations as per
  2. from time import time
  3. start = time()

  4. def isPrime1(num):
  5.         if num == 2 or num ==3:
  6.                 return True
  7.         elif num%2 == 0:
  8.                 return False
  9.         elif (num-1) % 6 != 0 and (num+1) % 6 != 0:
  10.                 return False
  11.         else:
  12.                 for i in range(3,int(num**0.5+1),2):
  13.                         if num%i == 0:
  14.                                 return False
  15.                 return True
  16.    
  17. def getPan1(n):
  18.         pan = per(range(1,n+1),n)
  19.         panlist = []
  20.         for each in pan:
  21.             ee = 0
  22.             for e in each:
  23.                 ee = ee*10 + e
  24.             panlist.append(ee)
  25.         return panlist

  26. for k in range(9,1,-1):
  27.         testpan = reversed(getPan1(k))
  28.         for eachpan in testpan:
  29.                 if isPrime1(eachpan):
  30.                     print (eachpan)
  31.                     end = time()
  32.                     print ('Use: %.3f sec.' % (end-start))
  33.                     exit()
复制代码

        我主要想通过这个例子告诉大家,其实,编程语言固然重要(Python是个非常好的工具,感谢小甲鱼的视频课程,我目前学习了1个月的时间,收益匪浅!),但是一个合理的算法往往比编程语言本身更重要。不要看几个毫秒好像和几秒差别不大,但是如果放到大数量级的地方,往往就是算得出和算不出的差别。
        最后,我想说,算法其实没有好坏之分,只有合适和不合适之别。暴力算法确实是最“笨”的办法,但是当你一头雾水、毫无头绪的时候,暴力算法往往是最直接有效的算法,而且不需要特别高深的数学知识,只需要把描述变成计算机语言即可(对数据量不是特别大的情况都适用)。
        感谢大家耐心看完本篇,我的程序也不是最优的程序,还有多种方法可以继续优化下去。但是对于本题来说,应该足够了。

评分

参与人数 1荣誉 +15 鱼币 +15 收起 理由
冬雪雪冬 + 15 + 15 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2016-10-17 15:09:48 | 显示全部楼层
本帖最后由 富友郑鹏展 于 2016-10-18 15:36 编辑

本程序使用Python2
  1. # # coding=utf-8


  2. # coding=utf-8

  3. import time
  4. import math as m

  5. # 判断一个数是否是质数
  6. def prime_number(n):
  7.     for i in xrange(2, int(m.sqrt(n))+1):
  8.         if n % i != 0:
  9.             continue
  10.         else:
  11.             return False
  12.     else:
  13.         return True

  14. # 判断每个位数是否重复
  15. def num_repeat(n):
  16.     str_num = str(n)
  17.     for i in str_num:
  18.         if str_num.count(str(i)) == 1:
  19.             continue
  20.         else:
  21.             return True
  22.     else:
  23.         return False

  24. # 判断每个位数是否连续
  25. def bit(n):
  26.     str_num = str(n)
  27.     b = len(str_num)
  28.     for i in xrange(b):
  29.         if str(i+1) in str_num:
  30.             continue
  31.         else:
  32.             return False
  33.     else:
  34.         return True



  35. # 找出最大的pandigital数
  36. # 由于3的倍数的特点,所有8位数和9位pandigital数都不是质数,所以从7位数开始找
  37. num = 7654321
  38. num_list = []
  39. start = time.time()
  40. while num > 0:
  41.     if num % 2 != 0 and num % 3 != 0 and num % 5 != 0:
  42.         if num_repeat(num) is False:
  43.             if bit(num) is True:
  44.                 if prime_number(num) is True:
  45.                     print '最大的pandigital质数是:%s' % num
  46.                     break
  47.                 else:
  48.                     num -= 1
  49.             else:
  50.                 num -= 1
  51.         else:
  52.             num -= 1
  53.     else:
  54.         num -= 1

  55. print 'use time:%s s' % (time.time() - start)
复制代码


结果:
QQ截图20161018153538.png

评分

参与人数 1荣誉 +15 鱼币 +15 收起 理由
冬雪雪冬 + 15 + 15 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-18 12:46:39 | 显示全部楼层
  1. from time import time
  2. start=time()
  3. save=[];N=1
  4. def calculation(i):                #判断是否为n位的 pandigital 数
  5.         j=1;
  6.         x=str(i)
  7.         while j<=len(x):
  8.                 p=str(j)
  9.                 a=x.count(p)
  10.                 if (a!=1) or ('0'in x):
  11.                         break
  12.                 j+=1
  13.         if j==(len(x)+1):
  14.                 return 1
  15.         else:
  16.                 return 0

  17. def judge(N):                #判断是否为质数
  18.         k=2
  19.         while k<=int((N**0.5)+1):
  20.                 if N%k==0:
  21.                         break
  22.                 k+=1
  23.         if k==(int((N**0.5)+1)+1):
  24.                 return 1
  25.         else:
  26.                 return 0
  27.         
  28. while N<=7654321:                #8为和9位的pandigital数,必能被3整除,不是质数
  29.         if calculation(N) :
  30.                 if judge(N):
  31.                         save.append(N)
  32.         N+=1
  33.                
  34. print(max(save))
  35. print('time=%f'%(time()-start))
复制代码


结果:
  1. 7652413
  2. time=10.644090
复制代码

评分

参与人数 1荣誉 +10 鱼币 +10 收起 理由
冬雪雪冬 + 10 + 10 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-18 17:24:45 | 显示全部楼层
本帖最后由 bacon6581 于 2016-10-22 02:23 编辑

前言:
最大的pandigital数当然是9位了,而且是且仅是987654321
于是我就第一位先取9、再取8....
第二位先取 去掉第一位里的最大值,再取第二大的...
......
结果发现没有结果,校对了几次,还是没有结果....
再看题:n 位的 pandigital 数,原来n不一定等于9
----------------------------------------------------------------
那就当是8位,试了下,还是没有结果
再试7位,出来结果了7652413
后来一分析:
1+2+3+4+5+6+7+8+9能被3整除,也就是任意组合必能被3整除
1+2+3+4+5+6+7+8也能被3整除
直接只写7位数,不停的组合,然后判断是否质数,觉得不是很好
因为我已知结果是7位数了,如果一开始不知道是7位数,应该考虑其他位数的组合
花了半天的时间改进了下代码,从51行起,修改了代码
51行往上的,懒得改了!
-----------------------------------------------
0、先求出一批质数(2,987654321**0.5)之间的,用来快速判断组合是否质数
1、组合中数字之和能被3整除的,直接跳过,且舍弃该组合的最大一位数
      如:【1、2、3、4、5、6、7、8】能被3整除,就不考虑它们的组合了,
             舍掉最大值8,考虑【1、2、3、4、5、6、7】的组合
2、先求出该组合的长度,如【1、2、3、4、5、6、7】的长度为7
3、第一位有'组合的长度'种方式,7种
4、第二位有'组合的长度-1'种方式,6种
5、第三位有'组合的长度-2'种方式,5种
.......
6、判断该组合是否质数,如果是质数,跳出多重循环
7、输出结果
---------------------------------------------------------------
这题学到的内容:
1、python里没有goto语句,百度里找了个跳出多重循环的方法
2、复制列表,不能简单用“=”来赋值

代码如下:
  1. from time import time
  2. start = time()

  3. class goto(Exception):pass

  4. zs_max=987654321**0.5
  5. zs=[2]
  6. x=2

  7. def zhishu(x):
  8.     zs_m=x**0.5
  9.     for i in zs:
  10.         if i>zs_m:
  11.             return True
  12.         if x%i==0:
  13.             return False
  14.         
  15. while x<zs_max:
  16.     x+=1
  17.     if zhishu(x)==True:
  18.         zs.append(x)

  19. shu=[10,9,8,7,6,5,4,3,2,1]

  20. try:
  21.     while 1:
  22.         shu.remove(shu[0])
  23.         jj=0
  24.         for j in shu:
  25.             jj+=j
  26.         if jj%3==0:
  27.             shu.remove(shu[0])
  28.             shu.remove(shu[0])
  29.         ln=len(shu)
  30.         
  31.         for s1 in range(0,ln):
  32.             shu1=shu[:]
  33.             result1=shu1.pop(s1)*100000000
  34.             for s2 in range(0,ln-1):
  35.                 shu2=shu1[:]
  36.                 result2=result1+shu2.pop(s2)*10000000
  37.                 for s3 in range(0,ln-2):
  38.                     shu3=shu2[:]
  39.                     result3=result2+shu3.pop(s3)*1000000
  40.                     for s4 in range(0,ln-3):
  41.                         shu4=shu3[:]
  42.                         result4=result3+shu4.pop(s4)*100000
  43.                         for s5 in range(0,ln-4):
  44.                             shu5=shu4[:]
  45.                             result5=result4+shu5.pop(s5)*10000
  46.                             if ln<7:
  47.                                 result8=result5/1000+shu5[0]
  48.                                 print(result8)
  49.                                 print(shu5)
  50.                                 if zhishu(result8)==True:
  51.                                     result=result8
  52.                                     raise goto()
  53.                             else:
  54.                                 for s6 in range(0,ln-5):
  55.                                     shu6=shu5[:]
  56.                                     result6=result5+shu6.pop(s6)*1000
  57.                                     if ln<8:
  58.                                         result8=result6/100+shu6[0]
  59.                                         if zhishu(result8)==True:
  60.                                             result=result8
  61.                                             raise goto()
  62.                                     else:
  63.                                         for s7 in range(0,ln-6):
  64.                                             shu7=shu6[:]
  65.                                             result7=result6+shu7.pop(s7)*100
  66.                                             if ln<9:
  67.                                                 result8=result7/10+shu7[0]
  68.                                                 if zhishu(result8)==True:
  69.                                                     result=result8
  70.                                                     raise goto()
  71.                                             else:
  72.                                                 for s8 in range(0,ln-7):
  73.                                                     shu8=shu7[:]
  74.                                                     result8=result7+shu8.pop(s8)*10+shu8[0]
  75.                                                     if zhishu(result8)==True:
  76.                                                         result=result8
  77.                                                         raise goto()

  78. except goto:
  79.     pass

  80. print(result)
  81. print(time()-start)
复制代码

  1. >>> ================================ RESTART ================================
  2. >>>
  3. 7652413.0
  4. 0.8639051914215088
  5. >>>
复制代码

评分

参与人数 1荣誉 +15 鱼币 +15 收起 理由
冬雪雪冬 + 15 + 15 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-18 17:57:26 | 显示全部楼层
本帖最后由 小剑剑 于 2016-10-18 18:01 编辑

从大到小产生pandigital数检验是否为质数
  1. from time import time
  2. from itertools import permutations
  3. from math import sqrt
  4. time1,if_find=time(),False
  5. def is_prime(num):#判断是否质数
  6.        if num<=1:
  7.               return False
  8.        else:
  9.               for i in range(2,int(sqrt(num))+1):
  10.                      if not (num%i):
  11.                             return False
  12.        return True
  13. def tupletoint(j):#把一个元组中的数字合成一个数字
  14.        le=len(j)
  15.        i=0
  16.        su=0
  17.        while i<le:
  18.               su=su*10+j[i]
  19.               i+=1
  20.        return su
  21. for i in range(9,0,-1):#这里的 i 是题中n
  22.       
  23.        itertuple=permutations([ii for ii in range(i,0,-1)],i)#产生pandigital数
  24.        for j in itertuple:
  25.               num=tupletoint(j)
  26.               if is_prime(num):
  27.                      time2,if_find=time(),True
  28.                      print(num,time2-time1)
  29.                      break
  30.        if if_find==True:
  31.               break
复制代码


答案7652413

评分

参与人数 1荣誉 +10 鱼币 +10 收起 理由
冬雪雪冬 + 10 + 10 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-18 18:14:12 | 显示全部楼层
本帖最后由 wangzhenas 于 2016-10-23 21:06 编辑

答案: 7652413
耗时:0.11000633239746094

思路是用range生成(1-n)的一个序列,然后用permutation生成所有排列,再这里只需要考虑到7位置,因为所有1-8,1-9组成的序列都能被3整除
reduce函数将比如[1,2,3,4]的序列生成为一个整数
最后用filter筛选出符合条件的质数并max出最大值


  1. from math import sqrt
  2. from itertools import permutations
  3. from functools import reduce
  4. from time import time

  5. t = time()

  6. def is_prime(num):
  7.     for n in (2,3,5):
  8.         if num%n == 0:
  9.             return False
  10.     for n in range(7,int(sqrt(num))+1,2):
  11.         if num%n == 0:
  12.             return False
  13.     return True
  14.    

  15. print(max(filter(is_prime,(reduce(lambda x,y: 10*x + y,num)
  16.                                             for i in range(5,7+1)
  17.                                                 for num in permutations(range(1,i+1)))
  18.                                                 )),time()-t)
复制代码

评分

参与人数 1荣誉 +10 鱼币 +10 收起 理由
冬雪雪冬 + 10 + 10 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-19 10:37:07 | 显示全部楼层
import time
st=time.time()
def pr(n):#定义一个质数判断函数
    if n==2:return True
    for j in range(2,int(n**0.5)+1):
        if n%j==0:
            return False
    return True

#pandigital数最大位是九位 但是8,9位pandigital数都能被3整除 所以最高位质数是7位数
for i in range(7654321,1000,-1):
    s=sorted('1234567')
    if pr(i) and sorted(str(i))==s:#判断i的质数性 和 pandigital性
        print(i)
        break
print(time.time()-st)

#输出
#7652413
#0.125

评分

参与人数 1荣誉 +10 鱼币 +10 收起 理由
冬雪雪冬 + 10 + 10 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-19 13:07:41 | 显示全部楼层
有数学知识可得,9位,8位的pandigital数不可能是素数
故直接从7位开始判断

  1. from itertools import permutations as per
  2. def prime(n): #判断素数
  3.     if n <= 1: return False
  4.     if n == 2: return True
  5.     for i in range(2,int(n**0.5)+1):
  6.         if n%i == 0: return False
  7.     return True
  8. num = lambda i: i[0]*1000000+i[1]*100000+i[2]*10000+i[3]*1000+i[4]*100+i[5]*10+i[6] #由元组生成pandigital数字
  9. for i in per([7, 6, 5, 4, 3, 2, 1]): #生成pandigital数
  10.     n = num(i)
  11.     if prime(n):
  12.         print(n)
  13.         break
复制代码

答案:7652413

评分

参与人数 1荣誉 +15 鱼币 +15 收起 理由
冬雪雪冬 + 15 + 15 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-21 13:18:39 | 显示全部楼层

  1. #! usr/bin/python
  2. # -*- coding:utf-8 -*-
  3. #python 2.7
  4. import itertools,math
  5. def isPrime(n):
  6.         if n == 1:
  7.             return False
  8.         elif n < 4:
  9.             return True
  10.         elif n & 1 == 0:
  11.             return False
  12.             
  13.         elif n < 9:
  14.             return True
  15.         elif n %3 == 0:
  16.             return False
  17.         else:
  18.                 r = math.floor(math.sqrt(n))
  19.                 f = 5
  20.                 while f <= r:
  21.                    if n % f == 0:
  22.                        return False
  23.                    if n %(f+2) == 0:
  24.                        return False
  25.                    f += 6
  26.                 return True   


  27. n = input('input n (n>1):')
  28. if str(n).isdigit() and int(n)>1:
  29.         n = int(n)
  30.         tmp =list(itertools.permutations(xrange(1,n+1),n))
  31.         #tmp = map(lambda x:int(''.join(map(str,x))),tmp)
  32.         max_ = None
  33.         for i in tmp:
  34.             num = int(''.join(map(str,i)))
  35.             #print num
  36.             max_ = [max_,max(max_,num)][isPrime(num) is True]
  37.         print max_
  38. else:
  39.         print 'n is not a int or n is <= 1'
复制代码


'''
========== RESTART: C:\Users\Administrator\Desktop\pycode\hosts.py ==========
input n (n>1):4
4231
>>>
input n (n>1):7
7652413
>>>
'''

评分

参与人数 1荣誉 +7 鱼币 +7 收起 理由
冬雪雪冬 + 7 + 7 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-21 13:28:38 | 显示全部楼层
  1. def isPrime(n):  #质数判断
  2.     for i in range(2,int(n/2)+1):
  3.         if n%i ==0:
  4.             return False
  5.     return True

  6. def isDigital(n):  #digital数判断
  7.     b=int(max(str(n)))
  8.     if sorted(str(n))==[str(i) for i in range(1,b+1)]:
  9.         return True
  10.     else:
  11.         return False

  12. def main():
  13.     for n in [7,4]:    #digital数位数n循环,2、3、5、6、8、9位digital数均能被3整除
  14.         x=''                    #获得最大的n位digital数
  15.         for i in range(n,0,-1):   
  16.             x+=str(i)
  17.         num1=int(x)
  18.         y=''            #获得最小的n位digital数
  19.         for i in range(1,n+1):
  20.             y+=str(i)
  21.         num2=int(y)
  22.         
  23.         for i in range(num1,num2-1,-9):    #digital数相差9的倍数
  24.             if isDigital(i)and isPrime(i):
  25.                     print('找到了',i)
  26.                     return

  27. if __name__=='__main__':
  28.     main()
复制代码


方法比较笨,没想到更好的digital数排列组合方法。
结果是7652413

评分

参与人数 1荣誉 +10 鱼币 +10 收起 理由
冬雪雪冬 + 10 + 10 热爱鱼C^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-23 22:05:38 | 显示全部楼层
本帖最后由 FDMa 于 2016-10-23 22:32 编辑

7652413,找到这么一个数,我也不知道是不是最大的
如果n=13,或者更大怎么算
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-11-14 21:29:18 | 显示全部楼层
jerryxjr1220 发表于 2016-10-17 11:05
这题其实有好多解法,我也想正好借这题,分享一些使用python解决一些数学题的心得。
【版主,在比赛结束后 ...

写的很好,思路简明清晰,看了这么多有关质数判断的帖子,这一篇写的最好
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-11-15 08:33:03 | 显示全部楼层
非常棒,围观学习
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-3-1 14:10:13 | 显示全部楼层

  1. from time import time
  2. from itertools import permutations

  3. def isPrime(n):
  4.     if n <= 1:
  5.         return False
  6.     elif n == 2 or n == 3:
  7.         return True
  8.     else:
  9.         for i in range(2, int(n**0.5)+1):
  10.             if n % i == 0:
  11.                 return False
  12.         else:
  13.             return True

  14. t1 = time()
  15. maxPandigital = 0
  16. for i in range(9, 0, -1):
  17.     a = permutations('123456789'[:i], i)
  18.     for j in a:
  19.         number = int(''.join(j))
  20.         if isPrime(number) and number > maxPandigital:
  21.             maxPandigital = number
  22. t2 = time()
  23. print(maxPandigital)
  24. print(t2 - t1)

  25. ##    7652413
  26. ##    1.65625
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-23 17:42

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表