题目描述:
斐波那契数列,是一个数学上著名的数列,这个数列{An}是这样的:1 1 2 3 5 8…
除了第一、二项之外,以后每项都是前两项的和
现给定n,请输出An。由于结果可能比较大,请输出An对19999999取余之后的结果
输入示例:
5
输出示例:
5
数据范围:
对于50%的数据,1≤n≤10^5
对于80%的数据,1≤n≤10^8
对于100%的数据,1≤n≤10^10
时间限制:
1s
空间限制:
128MB
题目分析:
对于斐波那契数列的描述,已经在题目描述中描述的非常清楚。但是这次的数据范围非常大,使用朴素的O(n)算法超时对于部分数据来说是必不可少的。因此我们需要寻找对数级别的算法,即O(logn)式算法,这就需要我们对题目进行分析。
首先我们对数据进行分析,对于100%的数据来说,1≤n≤10^10。要想拿到100%的分数,对于数据类型又是一个极大的挑战。long long int可能也没辙。出题者考虑到这一点,决定对数据进行大规模取余运算。这样的问题有两种解决方案,一是对n数据使用高精度计算,这暂时超出了我们目前的学习范围。二是利用初等的数论知识,对取余进行优化。
我们先来学习取余的几个性质:
1)
(a*b)%c=((a%c)*(b%c))%c
2)(a+b)%c=((a%c)+(b%c))%c
我们现假定这两个性质在数学上是正确的而略去其证明。
取余优化之后,我们回到最初的问题,该怎么找到一个时间复杂度为O(logn)的算法,来对计算斐波那契数列进行优化。
我们先来对斐波那契数列的通项公式进行分析:
An={1 (n=1,2)
An-1+an-2(n≥3)
}
好,这里我们就需要一些高等代数的知识了。
我们假定读者已经学过线性代数,并且可以基本掌握矩阵乘法的知识。
两个矩阵相乘首先要满足第一个矩阵的列数等于第二个矩阵的行数,而且要记住一点,矩阵乘法是不满足交换律的。至于矩阵乘法怎么算,假设A为m*p的一个矩阵,B为p*n的一个矩阵,用i表示行数,j表示列数,那A*B的结果中任意一项为 (A∗B)ij=∑pk=1aikbkj=ai1b1j+ai2b2j+...+aipbpj