如何求解:f(n) = f(n-1) + 3*f(n-2) + 3*f(n-3) + f(n-4)
Posted
技术标签:
【中文标题】如何求解:f(n) = f(n-1) + 3*f(n-2) + 3*f(n-3) + f(n-4)【英文标题】:how to solve: f(n) = f(n-1) + 3*f(n-2) + 3*f(n-3) + f(n-4) 【发布时间】:2014-11-02 05:42:49 【问题描述】:我该如何解决
f(n) = f(n-1) + 3*f(n-2) + 3*f(n-3) + f(n-4) maximum value of n = 10^18 minimum is 1
initial conditions are
f(1) = 1
f(2) = 3
f(3) = 3
f(4) = 1
f(n)
什么时候可以很大? print f(n) modulus 10000007
我对这个问题的尝试如下 (使用模数可能会出错)
1st test case:
3
2
5
9
output:
3
20
695
(working fine)
2nd tst case:
3
1554894
5959595
2562651
output:
7505501
9551828
6592801
(working fine)
但是对于更大的数字,程序会失败;为什么?
#!/usr/bin/python
T = int(raw_input())
def fib_iter(n):
if n == 1:
return 1
if n == 2:
return 3
if n == 3:
return 3
if n == 4:
return 1
prev1, prev2, prev3, prev4 = 1, 3, 3, 1
i = 5
while i < n+1:
curr = (prev1%10000007 + 3*prev2%10000007 + 3*prev3%10000007 + prev4%10000007)%10000007
prev1, prev2, prev3, prev4 = prev2%10000007, prev3%10000007, prev4%10000007, curr%10000007
i = i + 1
return curr%10000007
for t in xrange(T):
n = int(raw_input())
print fib_iter(n)
【问题讨论】:
您是否考虑过查看 google codejam 提交的解决方案? 这个问题似乎是题外话,因为它是一个“我可以危害 codez plz”的问题 ideone.com/qHudOC 我已经嵌入了我当前程序的链接......当输入很大(比如 10000000)并且给出错误的答案时,程序在执行过程中需要很长时间......但也给出了错误的答案 我建议您编写一个新问题,其中包含您的代码并说明您遇到的具体问题。简单地询问如何编写代码而没有其他任何事情不会得到有用的答案。 【参考方案1】:阅读this book,然后手工解决。
编辑: 当我被要求提供更多细节时:通过“求解”,我的意思是推导出一个直接给出系数 f(n) 的显式公式 [这样就没有递归必要的]。对于正常的斐波那契数列,这由比内公式给出。按照链接书中的食谱,您可以通过以下步骤完成:
导出第 n 个系数的生成函数。基本上,这是通过考虑一个函数来完成的,该函数在所寻求的系数 f(n) 方面具有幂级数展开,并将这几个项组合成一个函数。
给定生成函数,推导出单项式x^n前面的膨胀系数。由于您指定的生成函数最多包含四阶多项式,因此甚至可以通过解析来完成。
如果这里有一些数学模式,我会提供更多数学细节,如果运气好的话,我也会提供解决方案。但是就这样试试吧,它很简单,而且这本书可读性很好。
【讨论】:
虽然书籍推荐似乎不太适合这个网站,但似乎只能通过数学来解决【参考方案2】:更新 - 尝试将循环中的这两行更改为:
curr = (prev1 + 3*prev2 + 3*prev3 + prev4)%10000007
prev1, prev2, prev3, prev4 = curr, prev1, prev2, prev3
模数为 10000007,n = 15616511848,你应该得到 5370032,正如你提到的。请注意,10000007 = 941 x 10627 并且不是素数。我不确定为什么选择它。通常这些类型的问题使用 1000000007 (7 + 10^9) 这是一个素数。
加速这个算法更多的是一个数学问题,而不是一个编程问题。其矩阵形式为:
| 1 3 3 1 |
a = | 1 0 0 0 |
| 0 1 0 0 |
| 0 0 1 0 |
| 1 |
x[4] = | 3 |
| 3 |
| 1 |
x[i+1] = a x[i]
x[i+j] = a^j x[i]
可以使用重复平方来加快计算 a^j 的速度。
如果您对没有模数的 x[0] 到 x[4] 感到好奇。对于模数,将模数 (10000007) 添加到负数:
x[0] = -14, 39, -73, 117
x[1] = 1, -14, 39, -73
x[2] = 3, 1, -14, 39
x[3] = 3, 3, 1, -14
x[4] = 1, 3, 3, 1
【讨论】:
【参考方案3】:使用矩阵方法,执行变得非常快速和可靠。 http://x-perienceo.blogspot.in/
【讨论】:
【参考方案4】:我写了一个更详细的答案here。
重要的是要知道 1000007 是 素数。因此,您可以使用欧拉定理。欧拉定理指出,对于素数 p,a**x % p == a**y % p
(Python 表示法)如果 x % (p-1) == y % (p-1)
。
尝试找到一个矩阵符号来计算任何 n 的 f(n),而无需首先递归地计算 f(n-1) 等等。然后通过平方使用取幂来计算它(直到你的模,如上面 1. 中所述)。
【讨论】:
在这种情况下,使用的是 10000007,它不是素数,所以欧拉定理不适用,但这个问题不需要它,即使在对矩阵求平方时也是如此。 谢谢!!我已经使用矩阵方法解决了这个问题..非常快!!! x-perienceo.blogspot.in以上是关于如何求解:f(n) = f(n-1) + 3*f(n-2) + 3*f(n-3) + f(n-4)的主要内容,如果未能解决你的问题,请参考以下文章