Python n的第n个斐波那契数大到10^19?

Python n的第n个斐波那契数大到10^19?,python,python-2.7,dynamic-programming,fibonacci,Python,Python 2.7,Dynamic Programming,Fibonacci,我正试着做一个程序来找出1

我正试着做一个程序来找出1 这是我使用动态规划的代码

memo = {}
def fib(n):
    if n in memo:
        return memo[n]
    if n <= 2:
        f = 1
    else:
        f = fib(n-1) + fib(n-2)
    memo[n]=f
    return f
print fib(input()) % 1000000007
memo={}
def纤维(n):
如果备忘录中有n:
返回备忘录[n]
如果nPython的默认值为1000(通常)。要了解系统的确切限制,请执行以下操作:

>>> import sys
>>> sys.getrecursionlimit()
首先,如果您想递归地编写此代码,并且您使用的是Python 3.2及更高版本(从
print
语句判断,您看起来不是这样的),那么您可以这样使用:

导入工具
@functools.lru_cache()
def纤维(n):
如果n在O(n)效率下,你将永远无法到达那里。与代码无关,但描述了一种在O(log(n))效率中查找F(n)的方法

F(2n-1)=F(n-1)^2+F(n)^2

F(2n)=(2*F(n-1)+F(n))*F(n)


你不仅可以这样做,而且还可以递归地这样做。

当N为10^19时获取第N个fibonacci数是不可行的,如果你用天真的方法来做的话(至少我猜它不会起作用)

有一个更好的方法。这种技术适用于很多类似这样的系列。它叫“世界杯”

在哪里

你可以这样想:

你有一些矩阵可以把向量A转换成B:

填写这些条目很容易。特别的是这是一个矩阵算子,如果我们想要第1000个斐波那契数,我们只需要做矩阵乘法

你可以用一个循环来实现这一点,但要达到10^19还需要相当长的时间,而进行10^19矩阵乘法(即使它们很小)也需要相当长的时间

相反,我们走另一条捷径。x^N可以重写为幂的乘积,其中它们的和为N,即

x**100 == x**90 * x**10
因此,目标是在不进行大量计算的情况下获得指数中的大量数字:

x**2
x*x
一样困难-它们花费的时间相同。但是
x*x*x*x
给出了与
(x**2)**2
相同的答案,同时需要额外的乘法运算。当你进入更高的权力时,收益会更多。所以如果你把指数分解成2的幂(任何幂都有效,但这是最简单的情况)

i、 e

所以你要做的是,计算出你想要达到的总功率的二次幂,然后取
Q
矩阵的二次幂的乘积

这似乎对我有用:

fib_matrix = [[1,1],
              [1,0]]

def matrix_square(A, mod):
    return mat_mult(A,A,mod)


def mat_mult(A,B, mod):
  if mod is not None:
    return [[(A[0][0]*B[0][0] + A[0][1]*B[1][0])%mod, (A[0][0]*B[0][1] + A[0][1]*B[1][1])%mod],
            [(A[1][0]*B[0][0] + A[1][1]*B[1][0])%mod, (A[1][0]*B[0][1] + A[1][1]*B[1][1])%mod]]


def matrix_pow(M, power, mod):
    #Special definition for power=0:
    if power <= 0:
      return M

    powers =  list(reversed([True if i=="1" else False for i in bin(power)[2:]])) #Order is 1,2,4,8,16,...

    matrices = [None for _ in powers]
    matrices[0] = M

    for i in range(1,len(powers)):
        matrices[i] = matrix_square(matrices[i-1], mod)


    result = None

    for matrix, power in zip(matrices, powers):
        if power:
            if result is None:
                result = matrix
            else:
                result = mat_mult(result, matrix, mod)

    return result

print matrix_pow(fib_matrix, 10**19, 1000000007)[0][1]
fib_矩阵=[[1,1],
[1,0]]
def矩阵_平方(A,mod):
返回材料(A、A、mod)
def材料(A、B、mod):
如果mod不是None:
返回[[A[0][0]*B[0][0]+A[0][1]*B[1][0]%mod,(A[0][0]*B[0][1]+A[0][1]*B[1][1]%mod,
[A[1][0]*B[0][0]+A[1][1]*B[1][0]%mod,(A[1][0]*B[0][1]+A[1][1]*B[1][1]%mod]
def矩阵_功率(M、功率、mod):
#功率=0的特殊定义:

如果power我不认为您可以使用此选项升级到1E19,但以下是如何避免双重溢出和递归深度限制:

import decimal
import operator


def decimal_range(start, stop, step=1):
    """Provides an alternative to `xrange` for very high numbers."""
    proceed = operator.lt
    while proceed(start, stop):
        yield start
        start += step


def fib(n):
    """
    Computes Fibonacci numbers using decimal.Decimal for high 
    precision and without recursion
    """
    a, b = decimal.Decimal(0), decimal.Decimal(1)
    for i in decimal_range(0, n):
        a, b = b, a + b
    return a
在我的机器上,计算1E6需要26.5秒,但我不能保证结果的正确性:

In [26]: %time f2(n)
CPU times: user 26.4 s, sys: 130 ms, total: 26.5 s
Wall time: 26.5 s
Out[26]: Decimal('1.953282128707757731632014830E+208987')


迭代器是通过最小的改动从中获取的,同时可以找到
fib
函数。

您可以使用循环而不是递归。什么不起作用?您将达到递归深度限制。我得到无效响应。除了创建堆栈溢出的问题外,您可能只想存储最后两个Fibbonachi数,这样您就不会创建10^19个大整数的数组。此外,可能还可以查看一个多精度整数库,如gmpy2。OP没有很好地描述它,但我很确定OP的
%100000007
暗示了一个事实,即我们只需要得到mod 100000007的答案。不管怎样,矩阵形式(或者你喜欢的简化公式)可能是必要的,因为你无法对上限进行~10^19次迭代。@DSM你这样做的方式是首先不进行迭代。有一种更有效的方法来计算斐波那契数。@威尔:我不确定你的意思,因为我刚才说迭代是不可能的。使用矩阵乘法或等效的约化公式(正如我刚才所做的——我看到John Pirie刚刚发布的),我可以在大约190纳秒的时间内得到正确的答案。@DSM我只是在里面键入了一个类似这样的答案:-/@DSM我没有正确阅读你写的内容。我同意你的观点。+1,尽管这个公式对于直接计算
n
10^19
F(n)
仍然是没有希望的。(这里没有公式可以工作:结果太大,无法存储。)不过,再加上约化模
100000007
,这就行了。@Mark Dickinson:在对数(n)复杂度方面,我认为这个公式需要50次左右的迭代才能达到,不是吗?太多的辅助值无法计算?@JohnPirie:我想他只是指Fib(10^19)~2.2041233236015342e+2089876402499787337,所以除非我们减少,否则我们就被套住了。:-)@帝斯曼:啊,所以一个简单的估计也同样有效;感谢you@JohnPirie:是的,DSM说了什么。OP没有直接这么说,但看起来他真正想要的是减少模
F(n)
而不是
F(n)
本身。(听起来像是典型的Project Euler风格的挑战问题,而不是真实世界的计算。)如果你真的这么做了,那么你应该对矩阵进行对角化——然后你可以轻松地将其提升到任意幂次。嘿@will,这对斐波那契序列很有帮助。但是,有点离题了,但我希望你们能帮我-我有一个整数序列,其中有2n和2n+1项的自定义公式。你知道我是否可以用类似于斐波那契序列的方法来处理这个问题,并为自定义序列生成类似的Q矩阵吗?谢谢什么是递归关系?如果偏移量是固定的。
fib_matrix = [[1,1],
              [1,0]]

def matrix_square(A, mod):
    return mat_mult(A,A,mod)


def mat_mult(A,B, mod):
  if mod is not None:
    return [[(A[0][0]*B[0][0] + A[0][1]*B[1][0])%mod, (A[0][0]*B[0][1] + A[0][1]*B[1][1])%mod],
            [(A[1][0]*B[0][0] + A[1][1]*B[1][0])%mod, (A[1][0]*B[0][1] + A[1][1]*B[1][1])%mod]]


def matrix_pow(M, power, mod):
    #Special definition for power=0:
    if power <= 0:
      return M

    powers =  list(reversed([True if i=="1" else False for i in bin(power)[2:]])) #Order is 1,2,4,8,16,...

    matrices = [None for _ in powers]
    matrices[0] = M

    for i in range(1,len(powers)):
        matrices[i] = matrix_square(matrices[i-1], mod)


    result = None

    for matrix, power in zip(matrices, powers):
        if power:
            if result is None:
                result = matrix
            else:
                result = mat_mult(result, matrix, mod)

    return result

print matrix_pow(fib_matrix, 10**19, 1000000007)[0][1]
import decimal
import operator


def decimal_range(start, stop, step=1):
    """Provides an alternative to `xrange` for very high numbers."""
    proceed = operator.lt
    while proceed(start, stop):
        yield start
        start += step


def fib(n):
    """
    Computes Fibonacci numbers using decimal.Decimal for high 
    precision and without recursion
    """
    a, b = decimal.Decimal(0), decimal.Decimal(1)
    for i in decimal_range(0, n):
        a, b = b, a + b
    return a
In [26]: %time f2(n)
CPU times: user 26.4 s, sys: 130 ms, total: 26.5 s
Wall time: 26.5 s
Out[26]: Decimal('1.953282128707757731632014830E+208987')