分割倒数


21

给定一个n> 77的数字,编写一个程序或函数,以找到一组不同的正整数,使得该组的总和等于n,而该组的倒数之和等于1。

80的示例:

80 = 2 + 4 + 10 + 15 + 21 + 28⟶1/2 + 1/4 + 1/10 + 1/15 + 1/21 + 1/28 = 1

您的程序或函数必须(理论上)对n <2 32起作用,并且不能为浮点舍入错误辩解。请注意,存在所有n> 77的解


以字节为单位的最短代码获胜。

有一个额外的奖励措施:我将奖励适用于任何n并运行log(n)的最小解决方案。对于小n,它必须快速(由我自行决定)。是的,这是可能的。


3
这样的分解是否总是保证存在?有什么数论定理可以确保这一点?
Luis Mendo

似乎没有对所有的n> 77。(我没有检查所有细节。)那应该是在您的挑战的描述中……
更加糟糕的

1
@flawr,我想他没有包含该引用,因为它给出了O(log n)算法。
彼得·泰勒

1
他仍然应该提到对于给定的n存在此集合。(当我搜索标题时,我发现第一页上的文件。)
更加模糊的

1
@flawr,我花了大约10分钟才找到它。我是通过有关埃及分数的页面找到它的,您忍了10秒就对我了。
彼得·泰勒

Answers:


3

Mathematica,54个字节

Select[IntegerPartitions@#,Unequal@@#&&Tr[1/#]==1&,1]&

效率几乎没有问题,但确实能n = 78在9秒钟内解决。

结果以包裹在单例列表中的列表形式返回,例如:

{{45, 12, 9, 5, 4, 3}}

我想知道它是否适用于非常大的n。
njpipeorgan

@njpipeorgan有足够的内存和时间,可以。
Martin Ender

我发现了IntegerPartition [n]的长度的估计,大约为exp(sqrt(n)),对于n = 2 ^ 30约为10 ^ 10 ^ 4.5。我真的不相信mathematica(甚至任何架构)都能够容纳该数组。
njpipeorgan

@njpipeorgan挑战明确指出该算法在理论上必须达到2 ^ 32 ,而不是在实践上(通常是代码高尔夫所假定的,除非挑战明确要求程序实际上在合理的时间和内存内完成所有输入的程序)。
马丁·恩德

4

Python 3,7306 1995字节

该解决方案以log(n)复杂度运行(据我所知)。

def i(s,t):
 for n in s[::-1]:t=t.replace(*n)
 return [[]]*78+[list(bytearray.fromhex(a))for a in t.split(",")]
def f(n):
 g,h=lambda c,n:c+[[[2],[3,7,78,91]][n[len(c)]%2]+[i*2for i in c[-1]]],lambda n:[]if n<78 else h((n-[2,179][n%2])//2)+[n]
 v=h(n);c=[i([['g',',03040'],['h',',,0306080'],['i',',020'],['j','b0c1'],['k','21'],['l','60'],['m','30'],['n','141'],['o','k24'],['p',',g'],['q','618'],['r','0c0'],['s','1e'],['t',',0ml'],['u','283c'],['v','e0f1'],['w','2a38'],['x','80'],['y','a0'],['z','01'],['A','50'],['B','24'],['C','i40'],['D','plb1'],['E','gl'],['F','48'],['G','bre1'],['H','28'],['I','6k'],['J','416s'],['K',',040Al'],['L','90'],['M','2a'],['N','54'],['O','k6o'],['P','3c'],['Q','il'],['R','18'],['S','px'],['T','im'],['U','70'],['V','b1'],['W','23'],['X','pj'],['Y','hj'],['Z','0n']],'020lxycHTaRHCyf1517CyfneC91k51cCLdneQU912MCyf0dBiALyf2dClfPEyfneT9s2dELdneEjIgmLydHg5rd14BKLardsE3n8sQ9rd1517Q9rdneplmdRBgUmcRMC5sPEyf102bgA6sPE91z2miAj41IQmc0dRBQUen7spl31z82bT9RFT3wE7neMgmyf0dRBgUmaHMELc1b36EUdBMQLyfs2d,C710M2bgLardRHT3BFQ9rf0dPQ7rdBMQm9Rs2d,0mAl9100d142bE710M2bQmc0fRPtxarfn8sEc1k4sBTfnePExcwtxarf1k8BExcuT3kkT91663C51964,0mAl71k4BMELe12NTcRwQjOT820ltmarf1z8mExeRNCqBFtmyjIHKLa100ds2bQU91bM36garf1k4sBTcRBFgxarfwE91keB2dtUxcn8sME9nbs36gm9rduC5R78,0mAUyf0d14BME91kbB36QLc12AB2dgyjqkHEUeMNT9157eQU9RMFT8s78C8neuixLc1zk4AtUxc1z8Mmt8re0fn8sWhLyc1bH36pl8neu,Kxycsw,iAxc1420l,K8ren8NS9n81bs36hc0vz8WmYzqkmhyv2WBHhyVOHXkJoSjIwSjIuSvz4WASVZIAXZ6skmSj6oFXzOmplvcsW46D61csk46plv8WBFDqoF,tarvk8WBH,tyjkqoHhGqkN,tmvZ8sWmhVZqskmpc0vZ8WAXZqkAplbnImASbn6skwSbn6skuSVOwSVOupGONSbn6soFpyVkJk5aSj6sk78YJkuDkIP5aYOuhvzk4WBAhVzk416oA,tyjkJ265a,,0mxyjk41q53sYzIHmPXkqowXkqouhyVqoHFYz6omFhb0e1zqkmNSyVIP78YJ20klpyVOHwYk620olpc0vz8WBmFXzqomFpG61ckH38PhyjIP78Yz620kmlDkImLDzINUhGIuNDzIA78hb0e1ZIANYkqk366chG6oFNXkJkP5ahVZ6somFSb0e1620kNlhVk41qomADzIFLXkqso78pGqoFNXzkImP5a,tyjk620oHlhG620kNlXzqskm78,tjZqskHmPYqouFD6sku78YzqkNU,tjZqsomF')[v[0]]]
 for o in range(len(v)-1):c=g(c,v)
 return c[-1]

您可以测试f(2**32 - 1)几乎立即运行

我将本文用于一种计算方法。通过这种方法,n的预定值从78到334会有大量数据,而168之后没有偶数。做我自己的。

我压缩它的方式是通过列出字符串替换规则。我创建了一个方法,该方法找到了字符串替换规则,该规则将在考虑定义规则的情况下减少全部内容。然后,我递归地应用它,直到无法创建更多规则(我使用字符gz和AZ)。我替换为的字符串是每个数字的十六进制值的逗号分隔列表。回想起来,将它们转换为十六进制值可能不是最明智的选择,将它们保留为十进制可能会更短,因为使用十六进制将只保存3位数字,但为一位数字添加0。

在我设置c的行中,您可以看到替换规则的列表以及运行替换规则的文本。由于某些规则包含从其他规则创建的字符,因此也需要反向应用这些规则。

这段代码中还有很多地方可以减少语法,例如将列表列表变成单个列表,然后使用其他方法访问规则以将文本替换为


1
n=218输出[2]是预期的吗?
Officialaimm

1
不,我稍后会了解为什么会这样。我很抱歉。我最初压缩的数据可能是错误的。
卡梅隆·阿维克

1

Haskell,93个字节

import Data.List
import Data.Ratio
p n=[x|x<-subsequences[2..n],sum x==n,1==sum(map(1%)x)]!!0

太慢了1,但它在恒定内存中运行。平凡的解决方案:检查的所有子序列[2..n]求和和求和。

返回所有解决方案而不是一个的结果要短3个字节:只需删除!!0(请注意:运行时间将始终在图表之外)。


1运行时间取决于结果出现在子序列列表中的时间。如果找到第一个匹配项,Haskell的懒惰将停止搜索。编译后,p 89(结果[3,4,6,9,18,21,28]:)可以在35秒内在我(4岁)的笔记本电脑上运行。其他值,甚至更小的值,可能需要几个小时。


0

朱莉娅77字节

n->collect(filter(i->i==∪(i)&&sum(j->Rational(1,j),i)==1,partitions(n)))[1]

这是一个效率低下的lambda函数,它接受一个整数并返回一个整数数组。要调用它,请将其分配给变量。

我们使用获取整数的分区partitions。然后,我们仅对具有唯一元素且其倒数总和为1的那些分区进行过滤。为确保不发生舍入错误,我们使用Julia的Rational类型构造倒数。filter返回一个迭代器,因此我们必须将collect其放入数组。这给了我们一个数组数组(只有一个元素),所以我们可以使用第一个[1]

现在,当我说效率低下时,我是说真的。在我的计算机上运行n = 80会花费39.113秒,并分配13.759 GB内存。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.