Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 用Python计算模为m的巨大斐波那契数_Algorithm_Python 2.7_Fibonacci - Fatal编程技术网

Algorithm 用Python计算模为m的巨大斐波那契数

Algorithm 用Python计算模为m的巨大斐波那契数,algorithm,python-2.7,fibonacci,Algorithm,Python 2.7,Fibonacci,这个问题的目标是计算F[n]mod m。这里的输入是n和m,其中n表示斐波那契数的指数,比如F[0]=0,F[1]=1,F[2]=1,F[3]=2,m表示将被除以的数。制约因素包括: n>=1和n=2以及m=1和n=2和m我不明白您在查找维护程序(m)中试图做什么,或者为什么需要它。您已经在使用Fibonacci by double算法,它类似于(并且通常是从)矩阵平方求幂算法。通过在每一步修改部分结果,可以修改求幂运算以有效地处理模幂运算 def fibmod(n, m): asse

这个问题的目标是计算F[n]mod m。这里的输入是nm,其中n表示斐波那契数的指数,比如F[0]=0,F[1]=1,F[2]=1,F[3]=2,m表示将被除以的数。制约因素包括:


  • n>=1和n=2以及m=1和n=2和m我不明白您在
    查找维护程序(m)
    中试图做什么,或者为什么需要它。您已经在使用Fibonacci by double算法,它类似于(并且通常是从)矩阵平方求幂算法。通过在每一步修改部分结果,可以修改求幂运算以有效地处理模幂运算

    def fibmod(n, m):
        assert 1 <= n <= 10**18, n
        assert 2 <= m <= 10**5, m
    
        def f(n):
            if n == 0:
                return 0, 1
            else:
                a, b = f(n // 2)
                c = a * (2*b - a) % m
                d = (a**2 + b**2) % m
    
                if n % 2 == 0:
                    return c, d
                else:
                    return d, (c + d) % m
    
        return f(n)[0]
    
    def fibmod(n,m):
    
    assert 1通过使用模幂运算,可以非常快速地完成此操作

    考虑以下矩阵乘法:

    | 0  1 |     | a |     |  b  |
    |      |  x  |   |  =  |     |
    | 1  1 |     | b |     | a+b |
    
    如果
    a
    b
    是最后两项,那么您应该马上看到,此乘法的结果是斐波那契序列的下一次迭代。要获得执行此乘法
    n次的结果,需要计算2x2矩阵
    (0,1;1,1)
    (mod m)的
    n次
    幂。这可以通过将该矩阵提升到2的连续幂来快速完成

    例如,要计算此矩阵的第10次方:

                       | 0  1 |     | 0  1 |     | 1  1 |
    A x A  =  A**2  =  |      |  x  |      |  =  |      |
                       | 1  1 |     | 1  1 |     | 1  2 |
    
                          | 1  1 |     | 1  1 |     | 2  3 |
    A**4 =  (A**2)**2  =  |      |  x  |      |  =  |      |
                          | 1  2 |     | 1  2 |     | 3  5 |
    
                          | 2  3 |     | 2  3 |     | 13  21 |
    A**8 =  (A**4)**2  =  |      |  x  |      |  =  |        |
                          | 3  5 |     | 3  5 |     | 21  34 |
    
    将矩阵平方三次后,我们现在得到了
    A**8
    A**2
    的值。将这些值相乘,得到
    A**10

              | 13  21 |     | 1  1 |     | 34  55 |
    A**10  =  |        |  x  |      |  =  |        |
              | 21  34 |     | 1  2 |     | 55  89 |
    
    在常规算术中,这些数字将迅速变得巨大,但如果您以m为模执行所有乘法,则这不是问题。最后,将向量(0;1)乘以得到的矩阵,得到您的答案(或者,等效地,只需选择矩阵顶行中的第二个数字)

    所需的乘法次数约为
    log(n)
    ,因此所需的时间应该非常小,即使
    m
    为万亿或更多


    为什么这个问题陈述看起来如此熟悉?;-)竞争编程高手对此非常熟悉:这是www.spoj.com的FIB64问题。在g++8.3.0版(符合C++14)的英特尔G860 CPU arch=skylake上,在不到2秒钟的时间内要解决500000个fib(n)%m个测试用例n和m的大小为64位,即10^18。在英特尔上g++中长整型溢出的限制下,这对于模块化数学实现是一个很好的挑战。在Python中,溢出不是问题,但是Python在运行时500000次的速度太慢了。我的实现是在C++中,我用500000个快速的加倍时间来运行所有的这两个测试用例,但是我使用C++技巧来避免溢出,而不实现一个远远超出问题的目标的BigTigBand库。NB:对于Myz的外部库,禁止使用C++,甚至GMPY2禁止Python另一个注释:对于n=10 ^ 15,您的术语记忆以查找FIB(n)%m的周期不是一个好主意,因为N很大。关于这个数学问题,SPOJ还有另一个问题:它与米歇尔·雷诺(Michel Renault)的一个数学博士有关,用C++实现这个问题并不容易。在www.SPOJ.com上,关于斐波那契周期的问题名为PISANOfast Double,比模幂更快。请看我对findReminders尝试的记忆想法的评论。这种模式是存在的,但它涉及的数学远远超出了我们许多人的知识。论文脚本中的数学部分不完整,无法直接实现。
              | 13  21 |     | 1  1 |     | 34  55 |
    A**10  =  |        |  x  |      |  =  |        |
              | 21  34 |     | 1  2 |     | 55  89 |