两种方法求解Fibonacci数列
Fibonacci数列
定义:
F1 = F2 = 1 and Fn = Fn−1 +Fn−2
例:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …
循环迭代
这是最基础的方法,根据Fn = Fn-1 + Fn-2,从F1开始迭代到FN
#include <stdio.h>
int main(void){
int n;
while(EOF!=scanf("%d",&n)){
int f0 = 0;
int f1 = 1;
int fn;
if(0==n||1==n){
printf("%d\n",0==n?f0:f1);
continue;
}
for(int i=1;i<n;++i){
fn = f0 + f1;
f0 = f1;
f1 = fn;
}
printf("%d\n",fn);
}
return 0;
}
矩阵求解(快速幂)
在用矩阵求解Fibonacci前,我们先来看一个相关知识。
如何快速求解A^n次方。
可以用如下公式:
根据此公式,可以用递归的方式求解。
int POW(int a, int n)
{
if( n == 1 )
return a;
int result = 1;
int a1 = POW( a, k/2 );
a1 = a1*a1;
if( k & 1 )//奇数
result = result * a;
result = result * a1;
return result;
}
当然一般有递归就有循环的写法
注意到,
25=1∗2∗(22∗2……2)
5的二进制位101,和上面奇偶类似,末尾为1时,result*a, a = a*a
否则,只做a=a*a。第一位必为1,因此最后我们会把a乘回给result,不用担心丢失。
int power(int a,int n)
{
int result = 1;
while (n!=0)
{
if (n&1)//末位为1
{
result*= a;
}
a*= a;
n = n >> 1;//右移
}
return result;
}
下面来说用矩阵求解Fibonacci
有如下公式:
2维矩阵相乘可以如下表示:
其中,二维矩阵相乘可以如下表示:
void multiply(long long result[], long long factor1[], long long factor2[]) {
long long temp[] = { 0,0,0,0 };
temp[0] = (factor1[0] * factor2[0] + factor1[1] * factor2[2])%MOD;
temp[1] = (factor1[0] * factor2[1] + factor1[1] * factor2[3])%MOD;
temp[2] = (factor1[2] * factor2[0] + factor1[3] * factor2[2])%MOD;
temp[3] = (factor1[2] * factor2[1] + factor1[3] * factor2[3])%MOD;
for (int i = 0; i<4; ++i) {
result[i] = temp[i];
}
}
仿照上面求解A^n次方,最终可得如下代码:
void multiply(long long result[], long long factor1[], long long factor2[]);
const long long MOD = (int)pow(10,9)+7;
int main(void) {
long long int n;
while (scanf("%lld", &n) != EOF) {
if (0 == n || 1 == n || 2 == n) {
printf("%d\n", 0 == n ? 0 : 1);
continue;
}
long long result[] = { 1,0,1,0 };//单位矩阵
long long factor[] = { 1,1,1,0 };
n -= 1;
while (n) {
if ((n & 1) == 1) {
multiply(result, result, factor);
}
multiply(factor, factor, factor);
n >>= 1;
}
printf("%lld\n", result[0]);
}
return 0;
}
void multiply(long long result[], long long factor1[], long long factor2[]) {
long long temp[] = { 0,0,0,0 };
temp[0] = (factor1[0] * factor2[0] + factor1[1] * factor2[2])%MOD;
temp[1] = (factor1[0] * factor2[1] + factor1[1] * factor2[3])%MOD;
temp[2] = temp[1];
temp[3] = (factor1[2] * factor2[1] + factor1[3] * factor2[3])%MOD;
for (int i = 0; i<4; ++i) {
result[i] = temp[i];
}
}