在蓝桥杯官网做这道题,查阅网上大量代码后,竟没有一个用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)
以上文章如有错误,请评论告诉我,感激不尽