我已经在这个问题上苦苦挣扎了好几天了,我仍然是Python新手和更多的数学密集编码,所以任何帮助都会受到赞赏,只需指出我正确的方向:)
所以问题就像:
你有一个电影通行证,对 N 天有效。您可以以任何方式使用它,除了 连续3天或更长时间。
所以基本上,你既可以在某一天使用你的传球,也可以选择不传球,这意味着 2提升到N 的可能性。然后,声明通行证的有效方式是 2提升到N - invalidCases
您必须找到有效案例的数量%(10 ^ 9 + 7)
我找到了一个看似
的无效案例的递归关系invalidCases(at_N)= 2 ^(n-4)+ 2 * invalidCases(at_N-1) - invalidCases(at_n-4)
所以我的第一个冲动就是简单地使用递归:
def invalidCases(n):
if(n<3):
return 0;
elif(n==3):
return 1;
else:
return 2**(n-4)+ 2*invalidCases(n-1)- invalidCases(n-4)
非常低效,但我的等式似乎是正确的。 我的下一次尝试,我尝试了memoization,但我在N = 1006时遇到了错误。 所以我改变了递归限制。
我目前的尝试(记忆和增加的递归限制)
import sys
sys.setrecursionlimit(10**6)
T=int(input());
#2**(n-4) + 2*ans(n-1)-ans(n-4)
memo={0:0,1:0,2:0,3:1,4:3,5:8,6:20,7:47} #
def ans(n):
#complete this function
if n not in memo:
memo[n]=(2**(n-4) + 2*ans(n-1)-ans(n-4));
return memo[n];
modulo = 10**9 + 7;
print((2**n-ans(n))%modulo);
最后,我的问题。 我需要这段代码才能用于n = 999999。
如何将最坏情况降至最低? 任何指针或提示都会很棒。
答案 0 :(得分:0)
这是一个完整的解决方案,它基于以下观察:三天或三天以上的有效解决方案必须以下列之一开始:
0
10
110
其中1表示当天使用通行证,0表示不通行。
第一种形式有效(n-1)种可能性,第二种形式有效(n-2)种可能性,第三种形式有效(n-3)种可能性。
然后再次发生:
有效(n)=有效(n-1)+有效(n-2)+有效(n-3)
基本情况有效(0)= 1,有效(1)= 2,有效(2)= 4.重要的是要注意有效(0)是1,而不是零。这是因为当n = 0时恰好有一个解,即空序列。这不仅在数学上是正确的,而且还需要重现才能正常工作。
代码执行三项操作以使其快速运行:
以下是代码:
cache = {}
modulus = 10**9 + 7
def valid(n):
if n in cache:
return cache[n]
if n == 0:
v = 1
elif n == 1:
v = 2
elif n == 2:
v = 4
else:
v = valid(n-1) + valid(n-2) + valid(n-3)
v %= modulus
cache[n] = v
return v
def main():
# Preload the cache
for n in range(1000000):
valid(n)
print(valid(999999))
main()
这是输出:
746580045
它在我的系统上运行不到2秒。
更新:这是一个最小的迭代解决方案,受到MFisherKDX使用的方法的启发。种子值的构建方式不需要特殊套管(初始v2有效(0)):
modulus = 10**9 + 7
def valid(n):
v0, v1, v2 = 0, 1, 1
for i in range(n):
v0, v1, v2 = v1, v2, (v0 + v1 + v2) % modulus
return v2
print(valid(999999))
这个解决方案可能会尽可能快。它在使用它们后会丢弃中间结果,如果你只调用一次这个函数就没问题。
答案 1 :(得分:0)
这是我的答案。自下而上的解决方案。与汤姆的回答相比,回答是自上而下的,同样有效。在carthage update
的每一天,它会跟踪使用j
次传递的可能性数量,以及j
和{{1}使用传递的可能性数量}。
j
结果为j-1
,我的系统需要400毫秒。