Project Euler 60: Prime pair sets
素数3, 7, 109, 673很有意思,从中任取两个素数以任意顺序拼接起来形成的仍然是素数。例如,取出7和109,7109和1097都是素数。这四个素数的和是792,是具有这样性质的四个素数的最小的和。求满足以上性质的五个素数的最小的和。
分析:这道题的解法非常让人出人意料,这个问题实际上和图论中的的分团问题有关。要理解这个问题,我们需要知道一点图论中的基础知识。如果你已经对图论比较了解了,这一段可以跳过。图论属于组合数学的一个分支,图是图论的主要研究对象。所谓图是指由若干给定的顶点及连接两顶点的边所构成的图形,这种图形通常用来描述某些事物之间的关系。顶点用于代表事物,连接两顶点的边则用于表示两个事物间具有这种关系。图按其中的边是否有方向性可以分为有向图和无向图,按边是否有权重可以分为有权重图和无权重图,我们今天这里讨论的只是无权重的无向图,其它类型的图这里就不涉及了。
回到这里的问题,题目要求我们求出满足性质的五个素数的最小和,则我们首先需求找到这些满足性质的素数。这个性质即这些素数中两两之间可以正向和反向拼接仍能构成素数。我们可以把这些素数想像成为图中的节点,如果两个素数之间满足题目所说的性质,则我们可以在这两个素数之间画一条边。那么题目的问题就可以转换成,在一个由素数构成的图找到满足条件的五个顶点,这五个顶点两两之间都是联通的。现在我们可以明显看出来,这实际上就是图论中的分团问题。所谓分团问题(clique problem)是在一个图中找到一个完全子图,这个完全子图中的顶点两两之间都是相连接的。分团问题的一个典型应用是在社交网络分析当中,我们可以用图的顶点代表个人,用图的边代表两人之间相互认识,那么分团问题就相当于在某个人群找到一个小团体,这个小团体各个成员相互之间都认识。如在下图由六个顶点构成的图中,{1, 2, 5}三个顶点就构成了一个团,因为它们两两之间都相互连接的。
绝大部分分团问题都是困难的,即不存在多项式时间算法,但也存在一些比暴力求解更优的算法,如著名的Bron–Kerbosch算法,算法的细节大家可以参见这里。考虑到python中已经有比较完善的图论和网络分析的库也就是networkx,所以我们直接调用这个库来解决题目中的问题,这个库的使用方法请参见文档。首先我们要生成符合条件的素数对,我们编写了一个函数来判断特定的两个函数是否符合题目中的性质,这里一个优化的小细节是,大于三的所有素数期各位数之和除三的余数要不为一要不为二,当把两个素数拼接起来其各位数之和正好为两个素数的各位数之和的和,因此要满足题目的性质,这两个素数的各位数之和除三的余数必须要相同,否则两者拼接起来后各位数之和必然除三余零,即会被三整除不可能是一个素数。考虑到大于三的数和其各位数之和模三同余,则我们只需要比较两个素数除以三的余数是否相同就可以了。因为在判断两个素数是否满足性质时,同余运算比数字转字符串再拼接再转整数再判断是否为素数要快的多,因此在判断时先判断是否满足同余性质,不满足则不需要再进行之后的操作,从而可以大大节省判断的时间。
需要注意的是,在我们求满足条件的素数对时,需要给定一个合理的上界,这里只能先猜测,我首先把上界定到一万,求出小于一万的所有满足条件的素数对。然后把些素数对输入到networkx的图对象,成为这个图的一条条边,然后在这个图中使用find_cliques
函数找到所有顶点数为五的子图(这个函数实际上使用的是改进过的Bron–Kerbosch算法),然后在这些满足条件的子图中求出各个顶点之和的最小值。事实上,在一万的上界以内,满足条件的素数集合实际上只有一个,也就是 {13, 8389, 5701, 5197, 6733}这五个素数。为了验证以上素数集合确实是和最小的,我又求了十万以下的所有满足条件的素数集合,上面的给出的这个素数集合确实是和最小的,因此符合题目的所有条件。
最后一点可视化的工作:下图展示了一百五以内的所有素数中,满足题目中性质且大小为三的素数集合,可以明显发现共有三对(已经用青色标出),分别是{3, 7, 109}, {3, 37, 67}和{7, 19, 97}。可以看到,用图论解决题目中的问题是相当优雅且直观的。
最后,解题的代码如下:
# time cost = 2.82 s ± 83.9 ms
from sympy import isprime,primerange
import networkx as nx
from networkx.algorithms.clique import find_cliques
def is_pair_prime(x,y):
conc = lambda x,y:isprime(int(str(x)+str(y)))
if x == 3:
return conc(x,y) and conc(y,x)
else:
r = x % 3
return y%3==r and conc(x,y) and conc(y,x)
def main(N=8400):
res = []
primes = list(primerange(3,N))
index = 0
for p in primes:
index += 1
for i in primes[index:]:
if is_pair_prime(p,i):
res.append((p,i))
G = nx.Graph()
G.add_edges_from(res)
ans = [clique for clique in find_cliques(G) if len(clique)==5]
return min(map(sum,ans))
Project Euler 60: Prime pair sets的更多相关文章
- 欧拉工程第60题:Prime pair sets
题目链接 五个数,任意两个数的任意链接后的数还是质数 满足这个条件的最小五个数的和是多少? 结果:26033 纯暴力破解: package projecteuler51to60; import jav ...
- Project Euler 51: Prime digit replacements
通过替换*3这样一个两位数的第一位,我们可以发现形成的九个数字有六个是质数,即13, 23,43,53,73,83.类似的,如果我们用同样的数字替换56**3这样一个五位数的第三位和第四位,会生成56 ...
- Project Euler 44: Find the smallest pair of pentagonal numbers whose sum and difference is pentagonal.
In Problem 42 we dealt with triangular problems, in Problem 44 of Project Euler we deal with pentago ...
- project euler 169
project euler 169 题目链接:https://projecteuler.net/problem=169 参考题解:http://tieba.baidu.com/p/2738022069 ...
- Python练习题 048:Project Euler 021:10000以内所有亲和数之和
本题来自 Project Euler 第21题:https://projecteuler.net/problem=21 ''' Project Euler: Problem 21: Amicable ...
- Python练习题 039:Project Euler 011:网格中4个数字的最大乘积
本题来自 Project Euler 第11题:https://projecteuler.net/problem=11 # Project Euler: Problem 10: Largest pro ...
- Python练习题 035:Project Euler 007:第10001个素数
本题来自 Project Euler 第7题:https://projecteuler.net/problem=7 # Project Euler: Problem 7: 10001st prime ...
- Python练习题 031:Project Euler 003:最大质因数
本题来自 Project Euler 第3题:https://projecteuler.net/problem=3 # Project Euler: Problem 3: Largest prime ...
- [project euler] program 4
上一次接触 project euler 还是2011年的事情,做了前三道题,后来被第四题卡住了,前面几题的代码也没有保留下来. 今天试着暴力破解了一下,代码如下: (我大概是第 172,719 个解出 ...
随机推荐
- 你也可以写个服务器 - C# Socket学习2
前言 这里说的服务器是Web服务器,是类似IIS.Tomcat之类的,用来响应浏览器请求的服务. Socket模拟浏览器的Url Get请求 首先浏览器的请求是HTTP协议.我们上一篇说过,HTTP是 ...
- Redis学习三(进阶功能).
一.排序 redis 支持对 list,set 和 zset 元素的排序,排序的时间复杂度是 O(N+M*log(M)).(N 是集合大小,M 为返回元素的数量) sort key [BY patte ...
- opencv::模糊图像2
中值滤波 统计排序滤波器 中值对椒盐噪声有很好的抑制作用 medianBlur(Mat src, Mat dest, ksize) 双边滤波 均值模糊无法克服边缘像素信息丢失缺陷.原因是均值滤波是基于 ...
- php后端开发要学什么
PHP历史: 1994年创建,1995年对外发表第一个版本,名为:personal home page tools,之后发表PHP1.0.1995年中期,PHP2.0,从此建立了PHP在动态网站开发的 ...
- 使用docker-compose部署nginx+gunicorn+mariadb的django应用
目录 1. docker-compose 项目的组织目录 2. 构建 mysql 容器 3. 构建 django-blog 容器 4. 构建 nginx 容器 5. docker-compose.ya ...
- Spring Boot项目如何同时支持HTTP和HTTPS协议
如今,企业级应用程序的常见场景是同时支持HTTP和HTTPS两种协议,这篇文章考虑如何让Spring Boot应用程序同时支持HTTP和HTTPS两种协议. 准备 为了使用HTTPS连接器,需要生成一 ...
- 简单认识JVM
准备: 在具体聊JVM之前,我们先看两张图,通过分析图,咱们慢慢来聊聊JVM. JVM内存结构图 JVM内存结构脑图 上面两张图中,第二张图相对来说比较直观,就是JVM内存结构都划分成了哪些模块,各个 ...
- git jenkins SonarQube手动代码质检
SonarQube代码质检:1.提交代码-->gitlab-->jenkins抓取-->sonarqube质量检测-->maven编译-->shell-->web集 ...
- openresty性能测试报告分析
一.openresty介绍 1.什么是openresty 通过揉和众多设计良好的 Nginx 模块,OpenResty 有效地把 Nginx 服务器转变为一个强大的 Web 应用服务器,基于它开发人员 ...
- 【从刷面试题到构建知识体系】Java底层-synchronized锁-2偏向锁篇
上一篇通过构建金字塔结构,来从不同的角度,由浅入深的对synchronized关键字做了介绍, 快速跳转:https://www.cnblogs.com/xyang/p/11631866.html 本 ...