相信大家都已经知道这个中外著名的费波纳切数列了吧,关于费波那契数列有很多有趣的性质,但我们这里不讲,在这里我们只是利用斐波那契数列来引出另一个神奇的东西,矩阵乘法,递推在这里是起一个对比与铺垫的作用,(没有对比就不知道矩阵乘法有多快)。
定义一个数列
递推(我当大家都会了),但是这样的做法时间复杂度是 O(n) ,的,当n很大时,这个算法就会T。
斐波那契数列有一个通项公式,
知识预备:
①设
快速幂:
function f(a,b:extended;n:int64):int64;
var
t,y:extended;
begin
t:=1;
y:=a;
while b<>0 do
begin
if(b and 1)=1 then
t:=t*y mod n ;
y:=y*y mod n;
b:=b shr 1;
end;
exit(t);
end;
用快速幂求出斐波那契的第n项。
type
matrix=array[0..1,0..1] of int64;
const
mo=trunc(1e+8+7);
var
a,ans:array[0..1] of int64;
b,c,d:matrix;
i,j,k:longint;
n:int64;
procedure work(var a,b,c:matrix);//两个2*2的矩阵相乘
var
i,j,k:longint;
begin
for i:=0 to 1 do
begin
for j:=0 to 1 do
begin
for k:=0 to 1 do
begin
c[i,j]:=(c[i,j]+a[i,k]*b[k,j] mod mo) mod mo;
end;
end;
end;
end;
procedure fastpower(x:int64);
begin
c[0,0]:=1;
c[0,1]:=1;
c[1,0]:=1;
c[1,1]:=0;
b[0,0]:=1;//开始将B赋值为单位矩阵,相当于实数中1在乘法中的作用
b[1,1]:=1;
while x<>0 do
begin
if (x and 1)=1 then
begin
fillchar(d,sizeof(d),0);
work(b,c,d);
b:=d;
end;
fillchar(d,sizeof(d),0);
work(c,c,d);
c:=d;
x:=x div 2;
end;
end;
begin
readln(n);
if n=0 then
writeln(0);
if (n=1)or(n=2) then
writeln(1);
fastpower(n-1);
a[0]:=1;
a[1]:=0;
for i:=0 to 1 do
begin
for j:=0 to 1 do
begin
ans[i]:=(ans[i]+a[j]*b[j][i] mod mo) mod mo;
end;
end;
writeln(ans[0] mod mo);
end.
可以发现其实两者实质上是一样的,只是在计算的时候,一个用矩阵计算,另一个直接用一个变量计算,(矩阵其实也就是一堆变量)。
由于我的水平有限,难免有些会写错的,希望大家多多包容,批评指正,谢谢。