Algorithm 从给定的数中,确定三个闭合数,其乘积为原始数
我有一个数字Algorithm 从给定的数中,确定三个闭合数,其乘积为原始数,algorithm,math,language-agnostic,numbers,Algorithm,Math,Language Agnostic,Numbers,我有一个数字n,我想找到三个乘积为n但尽可能接近的数字。也就是说,如果n=12,那么我想得到3,2,2,而不是6,1,2 另一种思考方法是,如果n是长方体的体积,那么我想求边的长度,以便使长方体尽可能像一个立方体(也就是说,长度尽可能相似)。这些数字必须是整数 我知道不太可能有一个完美的解决方案,我很乐意使用一些大部分时间都能给出一个好答案的东西,但我就是想不出这个算法该怎么做。有什么想法吗?这是我的第一个算法草图,假设n相对较小: 计算n的值 选择三个最大的,并将它们分配到f1,f2,f3。
n
,我想找到三个乘积为n
但尽可能接近的数字。也就是说,如果n=12,那么我想得到3,2,2,而不是6,1,2
另一种思考方法是,如果n
是长方体的体积,那么我想求边的长度,以便使长方体尽可能像一个立方体(也就是说,长度尽可能相似)。这些数字必须是整数
我知道不太可能有一个完美的解决方案,我很乐意使用一些大部分时间都能给出一个好答案的东西,但我就是想不出这个算法该怎么做。有什么想法吗?这是我的第一个算法草图,假设
n
相对较小:
- 计算
的值n
- 选择三个最大的,并将它们分配到
,f1
,f2
。如果因子少于三个,则分配f3
1
- 按降序循环剩余的因子,将它们乘以当前最小的分区
编辑 让我们取
n=60
它的主要因素是5322
设置f1=5
,f2=3
和f3=2
剩余的2
乘以f3
,因为它是最小的
我们的结果是5*4*3=60
编辑 此算法不会找到最佳值,请注意注释:
考虑17550=2*3*3*5*5 * 13. 当最佳值为25、26、27时,您的算法将给出15、30、39
编辑 好的,这是我的第二个算法草图,带有稍微好一点的启发式:
- 将列表
设置为L
的值n
- 将
设置为r
的值n
- 创建三个因素的集合
,初始设置为F
1
- 按降序迭代素数因子:
- 尝试将当前系数
与每个系数按降序相乘。L[i]
- 如果结果小于
,则执行乘法并继续下一步 首要因素r
- 如果没有,请尝试下一个
。如果超出F
s,则与最小值相乘李>F
- 如果结果小于
- 尝试将当前系数
17550
:
n=17550
L=13,5,5,3,3,3,2
r=25.98
F = { 1, 1, 1 }
迭代1:
小于F[0]*13
,将r
设置为F
{13,1,1}
大于F[0]*5=65
r
小于F[1]*5=5
,将r
设置为F
{13,5,1}
大于F[0]*5=65
r
小于F[1]*5=25
,将r
设置为F
{13,25,1}
大于F[0]*3=39
r
大于F[1]*3=75
r
小于F[2]*3=3
,将r
设置为F
{13,25,3}
大于F[0]*3=39
r
大于F[1]*3=75
r
小于F[2]*3=9
,将r
设置为F
{13,25,9}
大于F[0]*3=39
r
大于F[1]*3=75
r
大于F[2]*3=27
,但它是我们能得到的最小F。将r
设置为F
{13,25,27}
比F[0]*2=26
大,但这是我们能得到的最小F。将r
设置为F
{26,25,27}
- 查找n的素数因子的三元组
列表KSetPartitions
- 将每个子集内的每个元素(素数因子)相乘,以产生n的三个因子的所有可能组合(当它们相乘时产生n)。你可以把除数想象成一个正交平行六面体的长度、宽度和高度
- 最靠近立方体的平行六面体的对角线空间最短。将每种情况下三个除数的平方和取最小值李>
以下是Mathematica中的代码:Needs["Combinatorica`"] g[n_] := Module[{factors = Join @@ ConstantArray @@@ FactorInteger[n]}, Sort[Union[Sort /@ Apply[Times, Union[Sort /@ KSetPartitions[factors, 3]], {2}]] /. {a_Integer, b_Integer, c_Integer} :> {Total[Power[{a, b, c}, 2]], {a, b, c}}][[1, 2]]]
它可以处理相当大的数,但随着n的因子数的增加,速度会大大减慢。下面的示例显示了240、2400、…24000000的计时。 考虑到一个因子在一个除数中出现多次的情况,原则上可以加快这一速度。我还不知道怎么做In[28]:= g[240] Out[28]= {5, 6, 8} In[27]:= t = Table[Timing[g[24*10^n]][[1]], {n, 6}] Out[27]= {0.001868, 0.012734, 0.102968, 1.02469, 10.4816, 105.444}
正如安德斯·林达尔(Anders Lindahl)所追求的那样,也许有一种聪明的方法可以找到最紧密的三胞胎,但我将重点介绍一种更基本的方法 如果我生成了所有的三元组,那么我可以根据需要过滤它们,所以我将从这里开始。我所知道的生成这些函数的最佳方法是使用递归:
此函数
接受两个整数参数,即系数f
的数量和产生系数n
的数量 这一节是k
使用#[[2;];;⌈ 长度@#/k⌉ ]] & @ 除数@n
生成除数
f[n_, 1] := {{n}} f[n_, k_] := Join @@ Table[ {q, ##} & @@@ Select[f[n/q, k - 1], #[[1]] >= q &], {q, #[[2 ;; ⌈ Length@#/k ⌉ ]] & @ Divisors @ n} ]
In[]:= f[240, 3] Out[]= {{2, 2, 60}, {2, 3, 40}, {2, 4, 30}, {2, 5, 24}, {2, 6, 20}, {2, 8, 15}, {2, 10, 12}, {3, 4, 20}, {3, 5, 16}, {3, 8, 10}, {4, 4, 15}, {4, 5, 12}, {4, 6, 10}, {5, 6, 8}}
Clear[poly, disc, f] poly = x^3 + a x^2 + b x + c; disc = Discriminant[poly, x]; f[n_Integer] := Module[{p, \[CapitalDelta] = disc /. c -> -n}, p = poly /. Maximize[{a, \[CapitalDelta] >= 0, b > 0 && a < 0 && {a, b} \[Element] Integers}, {a, b}][[ 2]] /. c -> -n; Solve[p == 0] ]
- 编辑
这里有一个简短的解释,使用更高效的代码,大大简化了事情。W先生也提出了一些建议。总体逻辑保持不变
假设至少有3个素数因子n