斐波那契数列笔记

 

  在中学时,我们就知道斐波那契数列是个很神奇的数列,在自然,生物,数学中都能找到他的影子,现在本人总结一下我关于斐波那契数列知识的例题。

  斐波那契数列公式:

  

  

  因为(1-sqrt(5))/2的绝对值小于1所以当i较大的时候,往往可以忽略掉这一项f(n)≈((1+Sqrt(5))/2)^n/sqrt(5);

 

斐波那契数列性质:

  1.斐波那契数列个位数数每60一循环

  2.当n大于1时,有F(n)和F(n-1)互质。

  3.若i为奇数, f(i)*f(i)=f(i-1)*f(i+1)+1,否则f(i)*f(i)=f(i-1)*f(i+1)-1

  4. f(n)=f(i)*f(n-i-1)+f(i+1)*f(n-i)

  5.齐肯多夫定理:任何一个正整数都可以表示为若干个不连续的斐波那契数之和。

定理证明:

 

    以F(n)来表示第n个斐波那契数。m为任意正整数。

 

    当m=1,2,3时,因为1=F(2),2=F(3),3=F(4),所以命题成立。下面采用数学归纳法证明定理对任何m均成立。

 

    假设定理对任何小于m的正整数数都成立。下证命题对m也成立。

 

    (1)若m是斐波那契数,则命题对m也成立。

 

    (2)若m不是斐波那契数,设n1是满足F(n1)< m < F(n1 +1)的最大正整数。

 

        设m'=m-F(n1),则m'=m-F(n1)<F(n1+1)-F(n1)=F(n1-1),即m'<F(n1-1)。

 

        m'<m,所以由归纳假设,m'可以表示成不连续的斐波那契数之和,即 m'=F(n2)+F(n3)+...+F(nt),
    其中n2>n3>...>nt,且是不连续的整数。又m'< F(n1-1),所以n2<n1-1,即n2与n1也是不连续的整数。

 

    故m=F(n1)+m'=F(n1)+F(n2)+F(n3)+...+F(nt),且n1>n2>...>nt是不连续的整数。

 

    因此,命题对m也成立。

 

 (证明来自百度百科)

 

斐波那契数列题:

  1. HDU 1568:http://acm.hdu.edu.cn/showproblem.php?pid=1568

  分析:题目要求斐波那契数的前4位,化简上面的公式有:f(n)=n*log10((1+sqrt(5))/2)-log10(sqrt(5));

 

  2. HDU 1021 :http://acm.hdu.edu.cn/showproblem.php?pid=1021

  分析:问第n个斐波那契数f(n)%3是否为0?算出前几个找规律:从2开始没4个一循环为yes。

 

   3.HDU 1588 Gauss Fibonacci:http://acm.hdu.edu.cn/showproblem.php?pid=1588

  分析:有g(i)=k*i+b;求F(g(i)) 其中i从0到n-1的和余上M的值,假设用S(n)来表示。那么我们首先推出S(n)的公式为:S(n)=F(g(0))+F(g(1))+F(g(2))+...+F(g(n-1))=F(b)+F(k*b)+F(2*k+b)+...+F((n-1)*k+b)。可以看出S(n)共有n项斐波那契数,一项项求斐波那契再求和是不现实的。较好的办法是把那n项斐波那契数用矩阵表示出来。对于第n项斐波那契,我们可以构造如下矩阵:

,那么对于S(n)我们就可以表示成如下矩阵形式:S(n)=Ab-1 *mat+Ak+b-1 *mat+A2*k+b-1 *mat+...+A(n-1)*k+b-1 *mat。我们令B=Ab-1 *mat,然后在提出公因式B。然后S(n)可化简为:S(n)=(I+Ak +A2*k+...+A(n-1)*k ) * B。再令D=Ak ,S(n)进一步化简为:S(n)=( I+D1 +D2 +...Dn-1 ) * B。到这里,S(n)的公式已经是最简单的了,并且也没必要再化简,因为到这里可以用二分法很快求的 D1 +D2 +...Dn-1的值。需要注意的是,k,b的值可能为0,对于这些特殊情况我们也要分情况讨论。

代码如下:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cmath>
  4 using namespace std;
  5 __int64 MOD;
  6 
  7 struct Matrix
  8 {
  9     __int64 map[2][2];
 10     int n;
 11     Matrix (int k=0)
 12     {
 13         n = 2;
 14         memset(map, 0, sizeof map);
 15         if(k) for(int i=0; i<2; i++)
 16             map[i][i] = 1;
 17     }
 18     Matrix operator * (const Matrix &a) const
 19     {
 20         Matrix e;
 21         for(int i=0; i<n; i++)
 22             for(int j=0; j<n; j++)
 23                 for(int k=0; k<n; k++)
 24                     e.map[i][j] = (e.map[i][j]+ map[i][k]*a.map[k][j]) % MOD;
 25         return e;
 26     }
 27     Matrix operator + (const Matrix &a) const
 28     {
 29         Matrix e;
 30         for(int i=0; i<n; i++)
 31             for(int j=0; j<n; j++)
 32                 e.map[i][j]=(map[i][j]+a.map[i][j]) % MOD;
 33         return e;
 34     }
 35     Matrix Pow(__int64 k) const
 36     {
 37         Matrix a = *this;
 38         Matrix e(1);
 39         while(k)
 40         {
 41             if(k&1)
 42                 e = e * a;
 43             a = a * a;
 44             k >>= 1;
 45         }
 46         return e;
 47     }
 48     Matrix operator * (const __int64 k) const
 49     {
 50         Matrix a = *this;
 51         for(int i=0; i<n; i++)
 52             for(int j=0; j<n; j++)
 53                 a.map[i][j] *= k;
 54         return a;
 55     }
 56     Matrix GuassSum(int k) const
 57     {
 58         Matrix a = *this;
 59         if(k==1) return a;
 60         Matrix t = this->GuassSum(k/2);
 61         if(k&1)
 62         {
 63             Matrix c = this->Pow(k/2+1);
 64             t = t + c + c * t;
 65         }
 66         else
 67         {
 68             Matrix c = this->Pow(k/2);
 69             t = t + t * c;
 70         }
 71         return t;
 72     }
 73     void print(char s[]="") const
 74     { 
 75         printf("Matrix %s:\n", s);
 76         for(int i=0; i<n; i++)
 77         {
 78             for(int j=0; j<n-1; j++)
 79                 printf("%I64d ",map[i][j]);
 80             printf("%I64d\n",map[i][n-1]);
 81         }
 82     }
 83 };
 84 
 85 int main()
 86 {
 87     Matrix base, mat, I(1);
 88     base.map[0][0]=base.map[0][1]=base.map[1][0] = 1;
 89     mat.map[0][0]=1;
 90     __int64 k, b, n;
 91     while(~scanf("%I64d %I64d %I64d %I64d",&k, &b, &n, &MOD))
 92     {
 93         if(k==0 && b==0)
 94             puts("0");
 95         else if(n==1)
 96             if(b==0)
 97                 puts("0");
 98             else
 99             {
100                 Matrix B = base.Pow(b-1) * mat;
101                 printf("%I64d\n", B.map[0][0]%MOD);
102             }
103         else if(b && k)
104         {
105             Matrix B = base.Pow(b-1) * mat;
106             Matrix D = base.Pow(k);
107             Matrix ans = (I + D.GuassSum(n-1)) * B;// 注意:矩阵乘法不满足交换律,次数若把B提到(I+D.GuassSum(n-1))前面会错。下同。
108             printf("%I64d\n", ans.map[0][0]%MOD);
109         }
110         else if(b==0 && k)
111         {
112             Matrix B = base.Pow(k-1) * mat;
113             Matrix D = base.Pow(k);
114             Matrix ans = (I + D.GuassSum(n-2)) * B;
115             printf("%I64d\n", ans.map[0][0]%MOD);
116         }
117         else if(b && k==0)
118         {
119             Matrix B = base.Pow(b-1) * mat;
120             B = B * n;
121             printf("%I64d\n", B.map[0][0]%MOD);
122         }
123     }
124     return 0;
125 }
View Code

 

转载于:https://www.cnblogs.com/khan724/p/4215965.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值