• 关于斐波拉契数列(Fibonacci)


    斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368........

    如果设F(n)为该数列的第n项(n∈N*),那么这句话可以写成如下形式::F(n)=F(n-1)+F(n-2) 。显然这是一个线性递推数列。
    通项公式:   ,又称为“比内公式”,是用无理数表示有理数的一个范例。
    斐波拉契数列也可用矩阵乘法+快速幂求出,其效率远优于以上两种解法O(logn)。
    斐波拉契数列在oi中常有出现,是比较重要的数论内容,部分数学结论与斐波拉契数列有关。
     
     
    Problem 1 [luogu P1349] 广义斐波那契数列

    题目描述

    广义的斐波那契数列是指形如an=p*an-1+q*an-2的数列。今给定数列的两系数p和q,以及数列的最前两项a1和a2,另给出两个整数n和m,试求数列的第n项an除以m的余数。

    输入输出格式

    输入格式:

    输入包含一行6个整数。依次是p,q,a1,a2,n,m,其中在p,q,a1,a2整数范围内,n和m在长整数范围内。

    输出格式:

    输出包含一行一个整数,即an除以m的余数。

     

     

     

    此题为斐波拉契数列的一个变形,即递推公式为f[i]=f[i-1]*a+f[i-2]*b;将矩阵变形即可。

     1 type
     2     rec                =record
     3     v                :array[0..2,0..2] of longint;
     4 end;
     5 
     6 var
     7     n,m,i,j,p,q,a1,a2            :longint;
     8     jz,ans                        :rec;
     9     
    10 function mul(a,b:rec):rec;
    11 var
    12     c                            :rec;
    13 begin
    14     c.v[0,0]:=(a.v[0,0]*b.v[0,0]+a.v[0,1]*b.v[1,0]+m) mod m;
    15     c.v[0,1]:=(a.v[0,0]*b.v[0,1]+a.v[0,1]*b.v[1,1]+m) mod m;
    16     c.v[1,0]:=(a.v[1,0]*b.v[0,0]+a.v[1,1]*b.v[1,0]+m) mod m;
    17     c.v[1,1]:=(a.v[1,0]*b.v[0,1]+a.v[1,1]*b.v[1,1]+m) mod m;
    18     exit(c);
    19 end;
    20     
    21 function pow(a:rec; k:longint):rec;
    22 begin
    23     if k=1 then exit(a);
    24     a:=pow(a,k>>1);
    25     if k mod 2=0 then exit(mul(a,a)) else exit(mul(mul(a,a),jz));
    26 end;    
    27     
    28 begin
    29     read(p,q,a1,a2,n,m);
    30     jz.v[0,0]:=0;
    31     jz.v[0,1]:=q;
    32     jz.v[1,0]:=1;
    33     jz.v[1,1]:=p;
    34     ans:=pow(jz,n-2);
    35     writeln(((ans.v[0,1]*a1+ans.v[1,1]*a2) mod m));
    36 end.

    Problem 2:Fibonacci

    【问题描述】

    斐波拉契有如下性质:F[1]=1,f[2]=1;F[n]=F[n-1]+F[n-2]是fibonacci的递推吧,求两项的最大公约数。

    【输入】

    第一行输入一个整数gay;gay<=10

    接下来的gay行,每行两个整数gay_a,gay_b;

    【输出】

    共gay行,每行一个整数,表示F[gay_a]和F[gay_b]最大公约数。(在MOD 19491001意义下)。

    input:

    5

    30 15

    14 28

    12 24

    17 17

    30 6

    output:

    610

    377

    144

    1597

    8

     

     

    我们先来看Fibonacci数列的几个引论

    引理1
    Gcd(F[n+1],F[n])=1;
    证明:
    根据辗转相减法则
    Gcd(F[n+1],F[n])=Gcd(F[n+1]-F[n],F[n])=Gcd(F[n],F[n-1])=Gcd(F[2],F[1])=1;

    引理2

    F[m+n]=F[m-1]F[n]+F[m]F[n+1]

    证明:

    F[n+m]=F[n+m-1]+F[n+m-2]=2*F[n+m-2]+F[n+m-3]=……

    F[n+m]=a[x]*F[n+m-x]+b[x]*F[n+m-x-1]=a[x]*(F[n+m-x-1]+F[n+m-x-2])+b[x]*(F[n+m-x-1)=(a[x]+b[x])*F[n+m+x-1]+a[x]*F[n+m+x-2];

    x=1时有 a[1]=F[2]; b[1]=F[1];

    x=2时有 a[2]=F[2]+F[1]=F[3];  b[2]=a[1]=F[2];

    x=k+1时有 a[k+1]=a[k]+b[k]=F[k+1]+F[k]=F[k+2] b[k+1]=a[k]=F[k+1];

    所以当x=n时 F[n+m]=a[n]F[m]+b[n]F[m-1]=F[n+1]F[m]+F[n]F[m-1];

    引理3

    Gcd(F[n+m],F[n])=Gcd(F[n],F[m])
    证明:
    Gcd(F[n+m],F[n])=Gcd(F[n+1]F[m]+F[n]F[m-1],F[n])=Gcd(F[n+1]F[m],F[n])=Gcd(F[n+1],F[n])*Gcd(F[m],F[n])=Gcd(F[m],F[n]);

    由以上三个引理有:Gcd(F[n],F[m])=F[Gcd(n,m)];


     如果不会证明也不知道结论怎么办?打表找规律即可AC。(像我一样)

     1 const mo=19491001;
     2 type
     3     rec                            =record
     4     v                            :array[0..1,0..1] of int64;
     5 end;
     6 
     7 var
     8     m,a,b                        :rec;
     9     n,i,j                        :longint;
    10     gc,x,y                        :int64;
    11     
    12 procedure csh;
    13 begin
    14     m.v[0,0]:=0;
    15     m.v[0,1]:=1;
    16     m.v[1,0]:=1;
    17     m.v[1,1]:=1;
    18 end;
    19 
    20 function mul(a,b:rec):rec;
    21 var
    22     c                            :rec;
    23 begin
    24     c.v[0,0]:=(a.v[0,0]*b.v[0,0]+a.v[0,1]*b.v[1,0]+mo) mod mo;
    25     c.v[0,1]:=(a.v[0,0]*b.v[0,1]+a.v[0,1]*b.v[1,1]+mo) mod mo;
    26     c.v[1,0]:=(a.v[1,0]*b.v[0,0]+a.v[1,1]*b.v[1,0]+mo) mod mo;
    27     c.v[1,1]:=(a.v[1,0]*b.v[0,1]+a.v[1,1]*b.v[1,1]+mo) mod mo;
    28     exit(c);
    29 end;
    30 
    31 function pow(a:rec; k:int64):rec;
    32 begin
    33     if k=1 then exit(a);
    34     a:=pow(a,k>>1);
    35     if k mod 2=0 then exit(mul(a,a)) else exit(mul(mul(a,a),m));
    36 end;
    37 
    38 function gcd(a,b:int64):int64;
    39 begin
    40     if (b=0) then exit(a);
    41     exit(gcd(b,a mod b));
    42 end;
    43     
    44 begin
    45     read(n);
    46     for i:=1 to n do
    47     begin
    48         csh;
    49         read(x,y);
    50         gc:=gcd(x,y);
    51         a:=pow(m,gc);
    52         writeln(a.v[0,1]);
    53     end;
    54 end.    

     

    Problem 3: 黄金分割比

    【问题描述】

    把一条线段分割为两部分,使其中一部分与全长之比等于另一部分与这部分之比。其比值是一个无理数,用分数表示为(√5-1)/2,取其前三位数字的近似值是0.618。由于按此比例设计的造型十分美丽,因此称为黄金分割,也称为中外比。这个分割点就叫做黄金分割点(golden section ratio通常用φ表示)这是一个十分有趣的数字,我们以0.618来近似表示,通过简单的计算就可以发现:(1-0.618)/0.618=0.6一条线段上有两个黄金分割点。

    现在LS要对这个数进行研究,首先他就要想办法用分数逼近黄金数。当然,他需要你给他的是离黄金数的差最小的分数。

    【输入】

    输入文件只有一行,这一行有一个数N(1≤N≤10^19),表示逼近的分数分母≤N。

    【输出】

    输出文件只有一行,这一行有一个分数,格式为“x/y”,为你所输出的分数。

    【输入输出样例】

    Gold.in

    10

    Gold.out

    5/8

    给出一个结论即可:而且当n趋向于无穷大时,斐波拉契数列前一项与后一项的比值越来越逼近黄金分割0.618,自己证明。

    注意,此题n较大,爆掉int64,需要特判一下。(或者你可以用高精)

     1 var
     2     f                            :Array[0..92] of int64;
     3     i,l                            :longint;
     4     s                            :int64;
     5     st                            :string;
     6     std                            :string;
     7 begin
     8     f[1]:=1;
     9     f[2]:=1;
    10     for i:=3 to 92 do f[i]:=f[i-1]+f[i-2];
    11     std:='7540113804746346429';
    12     readln(st);
    13     l:=length(st);
    14     if (l<19) or ((l=19) and (st<=std)) then
    15     begin
    16         val(st,s);
    17         if (s=1) or (s=0) then writeln('1/1') else
    18         begin
    19             for i:=1 to 92 do if s<=f[i] then break;
    20             if s=f[i] then writeln(f[i-1],'/',f[i]) else writeln(f[i-2],'/',f[i-1]);
    21         end;
    22     end else
    23     begin
    24         writeln('4660046610375530309/7540113804746346429');
    25     end;
    26 end.

     

  • 相关阅读:
    Windows下_findnext()异常问题
    Windows 10正式版官方原版镜像!(备忘)
    qt中出现error: C2059: 语法错误:“namespace”未定义等大量错误的问题
    linux shell的简单思维导图
    高仿花生壳客户端程序(qt)
    公告
    修改注册表自定义键盘快捷键
    斜率优化
    元旦老人与丛林
    CF 1466G Song of the Sirens
  • 原文地址:https://www.cnblogs.com/zoewilly/p/5998392.html
Copyright © 2020-2023  润新知