我最近对Project Euler非常沉迷,并且我正试图做下一个this!我已经开始对它进行一些分析,并且已经大大减少了问题。这是我的工作:
A = pqr和
1 / A = 1 / p + 1 / q + 1 / r所以pqr / A = pq + pr + qr
由于第一个等式:
pq + pr + qr = 1
因为p,q和r正好有两个 要消极,我们可以简化 等式找到:
abc,其中ab = ac + bc + 1
解决问题我们得到:
ab-1 =(a + b)c
c =(ab-1)/(a + b)
这意味着我们需要找到a和b 其中:
ab = 1(mod a + b)
然后我们的A值与那些a和 b是:
A = abc = ab(ab-1)/(a + b)
对不起,如果这是很多数学!但现在我们所要处理的只是一个条件和两个方程式。既然我需要找到写成ab(ab-1)/(a + b)且ab = 1(mod a + b)的第150,000个最小整数,理想情况下我想搜索(a,b)其中A是尽可能小。
为了方便起见,我假设一个< b我也注意到gcd(a,b)= 1。
我的第一个实施是直接的,甚至可以足够快地找到150,000个解决方案。但是,找到150,000个最小的解决方案需要太长时间。无论如何,这是代码:
n = 150000
seen = set()
a = 3
while len(seen) < n:
for b in range(2, a):
if (a*b)%(a+b) != 1: continue
seen.add(a*b*(a*b-1)//(a+b))
print(len(seen), (a, b), a*b*(a*b-1)//(a+b))
a += 1
我的下一个想法是使用Stern-Brocot树,但这太慢而无法找到解决方案。我的最终算法是使用中国余数定理来检查a + b的不同值是否产生解。该代码很复杂,虽然速度更快但速度不够快......
所以我完全没有想法!有人有任何想法吗?
答案 0 :(得分:4)
本文关于中文余下的快速实现,可以帮到您:www.codeproject.com/KB/recipes/CRP.aspx
这是工具和库的更多链接:
工具:
最大值 http://maxima.sourceforge.net/ Maxima是用于操纵符号和数值表达式的系统,包括微分,积分,泰勒级数,拉普拉斯变换,常微分方程,线性方程组,多项式和集合,列表,向量,矩阵和张量。 Maxima通过使用精确分数,任意精度整数和可变精度浮点数来产生高精度数值结果。 Maxima可以在二维和三维中绘制函数和数据。
Mathomatic http://mathomatic.org/math/ Mathomatic是一款免费,便携,通用的CAS(计算机代数系统)和计算器软件,可以象征性地求解,简化,组合和比较方程式,执行复数和多项式算术等。它可以进行一些微积分并且非常容易使用。
的Scilab www.scilab.org/download/index_download.php Scilab是一个类似于Matlab或Simulink的数值计算系统。 Scilab包含数百种数学函数,可以交互式添加各种语言(如C或Fortran)的程序。
mathstudio mathstudio.sourceforge.net 交互式公式编辑器和逐步求解器。
库:
Armadillo C ++库 http://arma.sourceforge.net/ Armadillo C ++库旨在为线性代数运算(矩阵和向量数学)提供有效的基础,同时具有简单易用的界面。
闪电++ http://www.oonumerics.org/blitz/ Blitz ++是一个用于科学计算的C ++类库
BigInteger C# http://msdn.microsoft.com/pt-br/magazine/cc163441.aspx
libapmath http://freshmeat.net/projects/libapmath 欢迎来到APMath项目的主页。这个项目的目标是实现任意精度的C ++ - 库,这是最方便使用的,这意味着所有操作都是作为操作符重载实现的,命名大多与。的相同。
libmat http://freshmeat.net/projects/libmat MAT是一个C ++数学模板类库。将此库用于各种矩阵运算,查找多项式的根,求解方程等。该库仅包含C ++头文件,因此无需编译。
animath http://www.yonsen.bz/animath/animath.html Animath是一个完全用C ++实现的有限元方法库。它适用于流体 - 结构相互作用模拟,它在数学上基于高阶四面体单元。
答案 1 :(得分:3)
与许多项目欧拉问题一样,诀窍是找到一种技术,将蛮力解决方案简化为更直接的事情:
A = pqr and
1/A = 1/p + 1/q + 1/r
所以,
pq + qr + rp = 1 or -r = (pq - 1)/(p + q)
不失一般性,0&lt; p&lt; -q&lt; -r
存在k,1 <= k <= p
-q = p + k
-r = (-p(p + k) – 1) / (p + -p – k) = (p^2 + 1)/k + p
但是r是一个整数,所以k除以p ^ 2 + 1
pqr = p(p + q)((p^2 + 1)/k + p)
因此,要计算A,我们需要迭代p,其中k只能取值为p平方加上1的除数。
将每个解决方案添加到集合中,当我们找到所需的第150000个亚历山大整数时,我们就可以停止。
答案 2 :(得分:0)
行。这里有一些我的中国剩余定理解决方案。事实证明,除非p = 1 (mod 4),否则a + b不能是任何素数p的乘积。这允许更快的计算,因为我们只需要检查a + b是素数的倍数,例如2,5,13,17,29,37 ......
所以这里是一个可能的a + b值的样本:
[5, 8, 10, 13, 16, 17, 20, 25, 26, 29, 32, 34, 37, 40, 41, 50, 52, 53, 58, 61, 64, 65, 68, 73, 74, 80, 82, 85, 89, 97, 100]
以下是使用中国剩余定理的完整程序:
cachef = {}
def factors(n):
if n in cachef: cachef[n]
i = 2
while i*i <= n:
if n%i == 0:
r = set([i])|factors(n//i)
cachef[n] = r
return r
i += 1
r = set([n])
cachef[n] = r
return r
cachet = {}
def table(n):
if n == 2: return 1
if n%4 != 1: return
if n in cachet: return cachet[n]
a1 = n-1
for a in range(1, n//2+1):
if (a*a)%n == a1:
cachet[n] = a
return a
cacheg = {}
def extended(a, b):
if a%b == 0:
return (0, 1)
else:
if (a, b) in cacheg: return cacheg[(a, b)]
x, y = extended(b, a%b)
x, y = y, x-y*(a//b)
cacheg[(a, b)] = (x, y)
return (x, y)
def go(n):
f = [a for a in factors(n)]
m = [table(a) for a in f]
N = 1
for a in f: N *= a
x = 0
for i in range(len(f)):
if not m[i]: return 0
s, t = extended(f[i], N//f[i])
x += t*m[i]*N//f[i]
x %= N
a = x
while a < n:
b = n-a
if (a*b-1)%(a+b) == 0: return a*b*(a*b-1)//(a+b)
a += N
li = [5, 8, 10, 13, 16, 17, 20, 25, 26, 29, 32, 34, 37, 40, 41, 50, 52, 53, 58, 61, 64, 65, 68, 73, 74, 80, 82, 85, 89, 97, 100]
r = set([6])
find = 6
for a in li:
g = go(a)
if g:
r.add(g)
#print(g)
else:
pass#print(a)
r = list(r)
r.sort()
print(r)
print(len(r), 'with', len(li), 'iterations')
这是更好的但我希望进一步改进它(例如a + b = 2 ^ n似乎永远不会是解决方案)。
我也开始考虑基本的替换,例如:
a = u + 1且b = v + 1
ab = 1(mod a + b)
uv + u + v = 0(mod u + v + 2)
然而,我不能看到很多改善......