Stern的双原子序列可以更详细地阅读over here;但是,为了我的目的,我现在将定义它。在
让n
是生成fusc
函数的数字。表示为fusc(n)
。在
如果n
为0,则返回值为0。
如果n
为1,则返回值为1。在
如果n
为偶数,则返回值为fusc(n / 2)
。
如果n
为奇数,则返回值为fusc((n - 1) / 2) + fusc((n + 1) / 2)
。在
目前,我的Python代码在大部分的生成过程中都是蛮力的,除了除以两部分之外,因为它永远不会产生任何变化。在
def fusc (n):
if n <= 1:
return n
while n > 2 and n % 2 == 0:
n /= 2
return fusc((n - 1) / 2) + fusc((n + 1) / 2)
但是,我的代码必须能够处理大小为1000s百万位的数字,并且递归地运行函数数千数百万次似乎不是非常有效或实用的。在
有没有什么方法可以在算法上改进我的代码,使大量的数字可以通过而不必递归调用函数那么多次?在
对于一百万位的记忆,递归堆栈将非常大。我们可以先看看一个足够大的数字,我们可以用手来计算,
fusc(71)
在这种情况下:我们意识到在这种情况下,我们可以完全避免递归,因为我们总是可以用
a * fusc(m) + b * fusc(m+1)
的形式来表达fusc(n)
,同时将m的值减少到0。从上面的示例中,您可能会发现以下模式:因此,您可以使用一个简单的循环函数在O(lg(n))时间内解决问题
lru_cache对你的情况很有帮助。确保
maxsize
是2的幂次方。你的应用程序可能需要调整一下这个尺寸。cache_info()
会有帮助的。在也可以使用
//
代替/
进行整数除法。在是的,这只是菲利普·马尔查克提出的一个建议。在
您可以在while循环中使用位操作获得额外的tiny加速:
^{pr2}$更新:
这里有一个简单的“手工”方法:
更新
在阅读了short article by dijkstra himself的小更新之后。在
文章指出,}相同,并且两者之间的位是颠倒的。这样做的目的是使
f(n) = f(m)
如果m
的第一位和最后一位与{n
越小越好。在这就是位掩码
(1<<n.bit_length()-1)-2
的用途(第一位和最后一位是0
;中间的那些1
;xor
ingn
,如上所述)。在我只能做一些小的基准测试;我感兴趣的是,如果这对您的输入的魔力有任何帮助。。。这将减少缓存的内存,并有望带来一些加速。在
我不得不增加递归限制:
基准测试给出了奇怪的结果;使用下面的代码并确保我总是启动一个新的interperter(有一个空的
_mem
),我有时会得到更好的运行时;在其他情况下,新代码会慢一些。。。在基准代码:
我得到了三个随机结果:
那就是我停下来的地方。。。在
相关问题 更多 >
编程相关推荐