题解 P1962 【斐波那契数列】
本人提供一种0ms的数学方法(pascal),时间复杂度为 lg(n)。不是通项公式,先看代码:
···pascal
var n,x,y,t:qword;
g:real;
procedure p(a:qword);
begin
if a=2 then
begin
x:=1; y:=1;
end else
if a mod 2=0 then
begin
p(a div 2);
t:=x*x+2*x*y;
y:=x*x+y*y;
x:=t;
end else
begin
p(a-1);
t:=x+y;
y:=x;
x:=t;
end;
x:=x mod 1000000007;
y:=y mod 1000000007;
//writeln(a,',',x,' ',a-1,',',y); readln;
end;
begin
readln(n);
if n=1 then
begin
writeln(1);
halt;
end;
p(n);
writeln(x);
// g:=sqrt(5);
//writeln(1/g*(c((1+g)/2,n)-c((1-g)/2,n)));
end.
··· 看看我的公式吧:
f(x)=f(x/2)^2 +2*f(x/2)*f(x/2-1) [x偶数]
f(x)=f(x/2+0.5)^2+f(x/2-0.5)^2 [x奇数]
怎么推的呢?
先看一个表吧
55 34 21 13 8 5 3 2 1 1 数列倒过来
10 9 8 7 6 5 4 3 2 1 编号
1 1个f(10)
0 1 1 f(9)+f(8) =f(10)
0 0 2 1 (把f (9)=f(8)+f(7) 代入上式) 2f(8)+f(7) =f(10
0 0 0 3 2 (把f (8)=f(7)+f(6) 代入上式) 3f(7)+2f(6) =f(10)
0 0 0 0 5 3 5f(6)+3f(5) =f(10)
正好,表中又藏了一个斐波那契,不难推出: f(10)=f(5)*f(6)+f(4)*f(5)
消元:
f(5)*f(6)+f(4)*f(5)=f(5)*( f(5)+f(4) )+f(4)*f(5)
化简、推广得:
f(x)=f(x/2)^2 +2*f(x/2)*f(x/2-1) [x偶数]
奇数再列表找规律,就可又获得一个公式:
f(x)=f(x/2+0.5)^2+f(x/2-0.5)^2 [x奇数]
把数列中相邻两个数看作“一对”,上面两个公式都是:
已知一对数,能求一个数,
比如 已知f(5)=5,f(4)=3,就能用公式1求出f(10), 用公式2求出f(9)
这样,已知一对数,就能求出另一对数;已知 f(x),f(x-1) ,就能求 f(2x),f(2x-1)
最后处理一下奇偶性问题,处理一下边界f(1)=1,即可
我的程序是用递归实现,p过程的意图是:
给出一个a,把f(a)的值赋给x,把f(a-1)的值赋给y 即
已知a,就能求出 f(a),f(a-1) 这一对数
t没有太多卵用,只作为临时变量