我有以下功能:
F(0) = 0
F(1) = 1
F(2) = 2
F(2*n) = F(n) + F(n+1) + n , n > 1
F(2*n+1) = F(n-1) + F(n) + 1, n >= 1
我收到了一个n < 10^25
号码,我必须证明其存在a
,例如F(a)=n
。由于函数的定义方式,可能存在n
,例如F(a)=F(b)=n where a < b
,在这种情况下,我必须返回b
而不是a
到目前为止我所拥有的是:
F(2*n) >= F(2*n+1) for any n
,所以我首先在F(2 * n)中搜索它,如果我在那里找不到它,我搜索F(2 * n + 1)< / LI>
我认为我有实际找到我需要的算法,但是我无法足够快地计算F(n)。
答案 0 :(得分:4)
只需使用记忆一直到目标值,例如在Python中:
class Memoize:
def __init__(self, fn):
self.fn = fn
self.memo = {}
def __call__(self, *args):
if not self.memo.has_key(args):
self.memo[args] = self.fn(*args)
return self.memo[args]
@Memoize
def R(n):
if n<=1: return 1
if n==2: return 2
n,rem = divmod(n,2)
if rem:
return R(n)+R(n-1)+1
return R(n)+R(n+1)+n
这会立即计算10 ** 25的答案。
这有效的原因是因为递归的性质意味着对于二进制数abcdef,它最多只需要使用这些值:
abcdef
abcde-1,abcde,abcde+1
abcd-2,abcd-1,abcd,abcd+1,abcd+2
abc-2,abc-1,abc,abc+1,abc+2
ab-2,ab-1,ab,ab+1,ab+2
a-2,a-1,a,a+1,a+2
在每一步中你可以向上或向下移动1,但你也可以将数字除以2,这样你离开原始数字的最多就是有限的。
因此,备忘录代码最多只能使用5 * log_2(n)个评估。