Fibonacci数列大数取模,用python实现(多种方法)

在蓝桥杯官网做这道题,查阅网上大量代码后,竟没有一个用Python实现的??(不得不说,python在算法比赛中依然很不受欢迎)
于是在这里分享一下自己的实现办法

先看一下题目要求
在这里插入图片描述
那其实主要问题就是如何实现斐波那契数列

1. 循环法:

这种办法速度很,但是代码很简单
因为python是可以很方便实现并行赋值
这里在循环中不断的更新列表,使得列表中储存 Fn 和 Fn-1


def Fibonacci():
    
    f1 = 1
    f2 = 1
    fibonacci = [f2, f1]
    n = int(input("输入n:"))
    if n == 1 or n == 2:
        return 1
    else:
        for i in range(n - 2):
            fibonacci[0], fibonacci[1] = fibonacci[0] + fibonacci[1], fibonacci[0]
        return fibonacci[0] % 10007
        
2.递归法:

这个方法也比较慢啊,把这个递归展开,是一个巨大的二叉树,重复子过程太多
而且。。。你可能会遇到这样的错误
RecursionError: maximum recursion depth exceeded in comparison
没错递归超过默认深度,我们知道无限递归会耗尽所有的资源,所以python很良心的为我们设置了最大深度为1000
你可以自行修改

import sys   
sys.setrecursionlimit(100000) #例如这里设置为十万
n = int(input("输入n:"))

def Fibonacci(_n):

    if _n == 1 or _n == 2:
        return 1
    else:
        return Fibonacci(_n - 1) + Fibonacci(_n - 2)
3.矩阵法:

终极大法,速度非常快
斐波那契数列是可以用矩阵来推导的,过程如下,有大一数学基础就可以看懂
在这里插入图片描述
因为矩阵是符合结合律的,所以我们只需要重复上述过程,即
在这里插入图片描述
但是算n次方依然很慢,那么我们只需要用一下快速幂,数万次的运算就能减少到几十次。快速幂的原理如下
在这里插入图片描述
所以每次计算之前,我们只需要判断一下n是奇数还是偶数,如果是偶数我们直接按上述运算即可。若果是奇数,我们不妨先和斐波那契矩阵先乘一次,这样就变成了偶次方运算。

因为python本身不带矩阵,所以我用二维列表模拟矩阵,自己写的矩阵乘法
(有些人可能会问我为什么不用numpy,矩阵乘法就是一行函数的事。。
下面我会解释)
先上代码


f1 = 1
f2 = 1
matrix_1 = [[1, 1], [1, 0]]
matrix_2 = [[], []]
f_matrix = [[f1], [f2]]
f_matrix_c = [[], []]
number = int(input()) - 2 # 输入n
if number == -1 or number == 0:
    print(1)
else:
    while not number == 1: # 当已经到一次方运算的时候,结束循环
        if number % 2 == 0:  # 偶次方运算
            matrix_2[0].append(matrix_1[0][0]**2 + matrix_1[1][0] * matrix_1[0][1])
            matrix_2[0].append(matrix_1[0][1] * matrix_1[0][0] + matrix_1[1][1] * matrix_1[0][1])
            matrix_2[1].append(matrix_1[0][0] * matrix_1[1][0] + matrix_1[1][0] * matrix_1[1][1])
            matrix_2[1].append(matrix_1[0][1] * matrix_1[1][0] + matrix_1[1][1]**2)
            matrix_1 = matrix_2
            matrix_2 = [[], []]  
            # 上面这一句是重中之重,是坑,不加上就全部GG
            # 因为不加就相当于:1和2两个矩阵还是都指向了一个内存地址的数组
            # 2矩阵没能发挥他真正的中间人作用
            number = number / 2

        elif number % 2 != 0: # 奇次方运算
            number = number - 1
            f_matrix_c[0].append(matrix_1[0][0] * f_matrix[0][0] + matrix_1[1][0] * f_matrix[1][0])
            f_matrix_c[1].append(matrix_1[0][1] * f_matrix[0][0] + matrix_1[1][1] * f_matrix[1][0])
            f_matrix = f_matrix_c
            f_matrix_c = [[], []]

            matrix_2[0].append(matrix_1[0][0] ** 2 + matrix_1[1][0] * matrix_1[0][1])
            matrix_2[0].append(matrix_1[0][1] * matrix_1[0][0] + matrix_1[1][1] * matrix_1[0][1])
            matrix_2[1].append(matrix_1[0][0] * matrix_1[1][0] + matrix_1[1][0] * matrix_1[1][1])
            matrix_2[1].append(matrix_1[0][1] * matrix_1[1][0] + matrix_1[1][1] ** 2)
            matrix_1 = matrix_2
            matrix_2 = [[], []]
            number = number / 2
    f_matrix_c[0].append(matrix_1[0][0] * f_matrix[0][0] + matrix_1[1][0] * f_matrix[1][0])
    print(f_matrix_c[0][0])
    print(f_matrix_c[0][0] % 10007)
    

为什么不用numpy:

当n很大时,因为numpy独特的数据类型限制,矩阵乘法将会溢出,而且据我所知,目前没有解决办法。。因为int64都不够,如果有大神知道请留言告诉我

详细解释请看另一篇文章:
https://blog.csdn.net/CxsGhost/article/details/103834353
放一下代码:


import numpy as np
f1 = 1
f2 = 1
_matrix = np.array([[1, 1], [1, 0]])
f_matrix = np.array([[f1], [f2]])
number = int(input()) - 2
if number == -1 or number == 0:
    print(1)
else:
    while not number == 1:
        if number % 2 == 0:
            _matrix = np.dot(_matrix, _matrix)
            number = number / 2

        elif number % 2 != 0:
            number = number - 1
            f_matrix = np.dot(_matrix, f_matrix)
            _matrix = np.dot(_matrix, _matrix)
            number = number / 2
            
	f_matrix = np.dot(_matrix, f_matrix)
    print(f_matrix[0][0] % 10007)
    

以上文章如有错误,请评论告诉我,感激不尽

发布了28 篇原创文章 · 获赞 74 · 访问量 1652

猜你喜欢

转载自blog.csdn.net/CxsGhost/article/details/103832939