牛的繁殖问题
问题描述
Description
Cows in the FooLand city are interesting animals. One of their specialties is related to producing offsprings. A cow in FooLand produces its first calve (female calf) at the age of two years and proceeds to produce other calves (one female calf a year).
Now the farmer Harold wants to know how many animals would he have at the end of N years, if we assume that none of the calves die, given that initially, he has only one female calf?
explanation:At the end of 1 year, he will have only 1 cow, at the end of 2 years he will have 2 animals (one parent cow C1 and other baby calf B1 which is the offspring of cow C1).At the end of 3 years, he will have 3 animals (one parent cow C1 and 2 female calves B1 and B2, C1 is the parent of B1 and B2).At the end of 4 years, he will have 5 animals (one parent cow C1, 3 offsprings of C1 i.e. B1, B2, B3 and one offspring of B1).
Input
The first line contains a single integer T denoting the number of test cases. Each line of the test case contains a single integer N as described in the problem.
Output
For each test case print in new line the number of animals expected at the end of N years modulo 10^9 + 7.
Sample Input 1
2
2
4
Sample Output 1
2
5
题目解析
就是求一个斐波那契数列中的某个数,只是这个数会很大,使用传统的方式会超时
思路解析
这里有两种方法
矩阵快速幂
斐波那契数列化成矩阵形式表达,有如下式子,(不理解的话乘一下就知道了)
[ F n − 1 F n − 2 ] × [ 1 1 1 0 ] = [ F n F n − 1 ] \left[\begin{array}{ccc}F_{n-1} & F_{n-2}\end{array}\right] \times \left[\begin{array}{ccc} 1 & 1 \\ 1 & 0 \end{array}\right] = \left[ \begin{array}{ccc}F_n & F_{n-1} \end{array}\right] [Fn−1Fn−2]×[1110]=[FnFn−1]
因此:
当n<2时,直接返回F2或F1即可,
当n>2时
定 义 初 始 矩 阵 ans = [ F 2 F 1 ] = [ 1 1 ] , base = [ 1 1 1 0 ] 定义初始矩阵\\ \text{ans} = \left[\begin{array}{ccc}F_2 & F_1\end{array}\right] = \left[\begin{array}{ccc}1 & 1\end{array}\right], \text{base} = \left[\begin{array}{ccc} 1 & 1 \\ 1 & 0 \end{array}\right] 定义初始矩阵ans=[F2F1]=[11],base=[1110]
那 么 , F n 就 等 于 ans × base n − 2 这 个 矩 阵 的 第 一 行 第 一 列 元 素 , 也 就 是 [ 1 1 ] × [ 1 1 1 0 ] n − 2 的 第 一 行 第 一 列 元 素 。 那么,F_n 就等于 \text{ans} \times \text{base}^{n-2}这个矩阵的第一行第一列元素,\\也就是 \left[\begin{array}{ccc}1 & 1\end{array}\right] \times \left[\begin{array}{ccc} 1 & 1 \\ 1 & 0 \end{array}\right]^{n-2} 的第一行第一列元素。 那么,Fn就等于ans×basen−2这个矩阵的第一行第一列元素,也就是[11]×[1110]n−2的第一行第一列元素。
也 就 是 b a s e n − 2 的 第 一 列 元 素 之 和 也就是{base}^{n-2}的第一列元素之和 也就是basen−2的第一列元素之和
公式法
利用Fibonacci递推公式:
F[2n] = F[n+1]² - F[n-1]² = (2F[n-1] + F[n]) · F[n] ①
F[2n+1] = F[n+1]² + F[n]² ②
利用map来暂时存储所需要的数据,即记录结果
代码实现(python)
快速幂
mod = 10 ** 9 + 7
def m_pow(cur, base): # 计算矩阵乘法
a1 = (cur[0][0] * base[0][0] + cur[0][1] * base[1][0]) % mod
a2 = (cur[0][0] * base[0][1] + cur[0][1] * base[1][1]) % mod
b1 = (cur[1][0] * base[0][0] + cur[1][1] * base[1][0]) % mod
b2 = (cur[1][0] * base[0][1] + cur[1][1] * base[1][1]) % mod
res = [[a1, a2], [b1, b2]]
return res
# 1 1 2 3 5 8 13
if __name__ == '__main__':
d = {1: 1, 2: 1}
for _ in range(int(input())):
n = int(input()) + 1
if n < 2:
print(d[n])
else: # 以下类似于普通快速幂
res = [[1, 0], [0, 1]] # 初始化结果矩阵,类似于快速幂中的ans
base = [[1, 1], [1, 0]] # 初始化base矩阵,类似于快速幂中的a
n = n - 2
while n > 0:
if n & 1 == 1: # 奇数
res = m_pow(res, base)
# 偶数
n = n // 2
base = m_pow(base, base)
ans = (res[0][0] + res[1][0]) % mod #求和
print(ans)
公式法
mod = 1000000007
d = {1: 1, 2: 1}
def fib(n):
if n < 3:
return d[n]
if n in d:
return d[n]
if (n % 2 == 1):
k = (n + 1) // 2
x = (fib(k) * fib(k) + fib(k - 1) * fib(k - 1)) % mod
d[n] = x # cache
else:
k = n // 2
x = (fib(k) * ((fib(k + 1) * 2) - fib(k))) % mod
d[n] = x
return d[n] # cache
for _ in range(int(input())):
n = int(input())
print(fib(n + 1))