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 个解出 ...
随机推荐
- 手把手教你吧Python应用到实际开发 不再空谈悟法☝☝☝
手把手教你吧Python应用到实际开发 不再空谈悟法☝☝☝ 想用python做机器学习吗,是不是在为从哪开始挠头?这里我假定你是新手,这篇文章里咱们一起用Python完成第一个机器学习项目.我会手把手 ...
- Python数据分析入门与实践 ✌✌
Python数据分析入门与实践 (一个人学习或许会很枯燥,但是寻找更多志同道合的朋友一起,学习将会变得更加有意义✌✌) 这是一个数据驱动的时代,想要从事机器学习.人工智能.数据挖掘等前沿技术,都离不开 ...
- 构造函数语义学——Default Constructor篇
构造函数语义学--Default Constructor 篇 这一章原书主要分析了:编译器关于对象构造过程的干涉,即在对象构造这个过程中,编译器到底在背后做了什么 这一章的重点在于 default c ...
- Java性能优化的小细节
性能优化实现方式(单纯考虑代码层面): 1.减小代码体积 2.提高运行效率 如何做: 1.尽量指定类.方法的final修饰符 带有final修饰的类是不可派生的,该类所有的方法都是final的,jav ...
- 概念理解:boost::asio::定时器2
多线程同步回调#include <cstdio> #include <iostream> #include <boost/asio.hpp> #include &l ...
- ajax 轮询(适合web端二维码请求)
(前几天 一直弄二维码轮询登录 想了半天 总算弄出来了 分享给大家 ^-^) 轮询: 所谓轮询 肯定需要 setInterval 但是怎么加ajax请求 需要有点小问题而且轮询成功后需要停 ...
- Java中package与import
使用实例: package 一般来说,package语句必须作为源文件的第一条非注释性语句.一个java源文件只能指定一个包,即只能包含一条package语句,该源文件中可以定义多个类,则这些类将全部 ...
- 移动端真机调试--weinre
一.安装 首先确保你的电脑上有node环境,然后使用cnpm或npm 安装 windows下 npm install weinre -g --registry=https://registry.npm ...
- 星云测试插装编译流程与CI集成
星云测试Horn插装采用脚本配置方式自动对语法进行扫描和插装,在整个插装过程中需要用到星云提供的插件工具.通过与CI集成,在CI编译前通过jenkins调用星云插装插件模块进行必要的数据填充,生成对应 ...
- 【ASP.NET Core学习】Razor页面
准备工作 初始化空的项目(终端输入:dotnet new web -n=Razor) Nuget添加Microsoft.EntityFrameworkCore.SqlServer 和 Microsof ...