// O(logN) 时间复杂度
// 计算经典斐波那契数列的某个数
// 1 2 3 5 8 13 21 34
// 如果只算一个数,二分很快 O(logn)
// 但如果全部输出,一个循环即可完成 O(n)
// 而不是二分计算每一个
// 借助斐波那契矩阵
// 1 2 n-1
// (f( n )) = ( 1 1 ) (f(n-1)) = ( 1 1 ) (f(n-2)) = ... = ( 1 1 ) (f(2))
// (f(n-1)) ( 1 0 ) (f(n-2)) ( 1 0 ) (f(n-3)) ( 1 0 ) (f(1))
//
// 这里计算 M的 a 次方
// 也就是 M^(a/2)^2
// 于是需要求 M^(a/2)
// 直到 M^1
// 显然二分递归计算
#include <stdio.h>
#define TYPE struct Fibo
#define X2(x) (x*x)
#define MAX_N 90
// 这里不拘泥于斐波那契矩阵的形式
// 而舍去了矩阵中一些不必要的东西
// (比如一直相等的数)
// ( 3 2 ) ---> { 3, 2, 1 }
// ( 2 1 )
TYPE
{
//int n;
long long int a[3];
}F1={ {1, 1, 0} };
//TYPE Fi[MAX_N];
TYPE cheng(TYPE f, int flag)
{
TYPE tf;
if(flag==1) // *F1
{
tf.a[0]=f.a[0]+f.a[1];
tf.a[1]=f.a[1]+f.a[2];
tf.a[2]=f.a[1];
}
else if(flag==2) // *itself
{
tf.a[0]=X2(f.a[0])+X2(f.a[1]);
tf.a[1]= f.a[0]*f.a[1]+f.a[1]*f.a[2];
tf.a[2]=X2(f.a[1])+X2(f.a[2]);
}
return tf;
}
TYPE deal(int n)
{
if(n<=1)return F1;
if(n%2==1)
return cheng(cheng(deal(n/2), 2), 1);
else
return cheng(deal(n/2), 2);
}
int main()
{
int n=MAX_N;
printf("F(%d) = %lld\n", n, deal(n).a[0]);
return 0;
}
O(logN) 计算经典斐波那契数列的某个数
最新推荐文章于 2022-12-21 19:14:48 发布