zoukankan      html  css  js  c++  java
  • 斐波那契加求幂运算

    斐波那契博大精深啊,还有求幂的迭代也有点意思

      1 //斐波那契有好多中方法
      2 #include <iostream>
      3 #include <deque>
      4 using namespace std;
      5 
      6 //注意普通斐波那契,在太大数时就会发生越界,比如long long 只能存表示第92个数,这些都是小的斐波那契,当要大时,就得用大数方法了
      7 //用int ,只能到第46个,47就不行了,unsighed int 只能到92
      8 int fibnaq(int n)             //采用vector或者deque的方法,用2个元素的话需要用到reverse,用三个元素的话可以不用,或者用2个元素用队列也可以
      9 {
     10     if(n<=0)
     11         return -1;
     12     deque<int> d(2);
     13     d[0]=1;
     14     d[1]=1;
     15     if(n==1||n==2)
     16         return 1;
     17     for(int i=3;i<=n;i++)
     18     {
     19         int tmp=d.front();
     20         d.pop_front();
     21         d.push_front(tmp+d.back());
     22         reverse(d.begin(),d.end());
     23     }
     24     return d.back();
     25 }
     26 int fibnaq2(int n)                  //数组实现,时间O(n),空间O(n)
     27 {
     28     int *A=new int[n];
     29     A[0]=1;
     30     A[1]=1;
     31     if(n==1||n==2)
     32         return 1;
     33     for(int i=2;i<n;i++)
     34     {
     35         A[i]=A[i-1]+A[i-2];
     36     }
     37     delete[] A;
     38     return A[n-1];
     39 }
     40 
     41 int fibnaq3(int n)  //迭代实现,时间O(n),空间O(1),其实就是vector的用3个int来做,辗转相加法
     42 {
     43     if(n<=0)
     44         return -1;
     45     int a=1,b=1,c;
     46     if(n==1||n==2)
     47         return 1;
     48     for(int i=3;i<=n;i++)
     49     {
     50         c=a+b;
     51         a=b;
     52         b=c;
     53     }
     54     return c;
     55 }
     56 long long fibnaq4(int n) //重头戏,公式法 f(n)=((1+根号5.0)的n次方-(1-根号5.0)的n次方)/((2.0的n次方)*根号5)
     57 {
     58     double gh5=sqrt(5.0);
     59     return (pow(1+gh5,n)-pow(1-gh5,n))/(pow(2.0,n)*gh5);
     60 }
     61 
     62 /*
     63 斐波那契数列是二阶递推数列,所以存在一个2*2的矩阵A,使得:
     64 (Fn, Fn-1) = (Fn-1, Fn-2)*A
     65 求得A=(1   1)
     66       (1   0)
     67 (fn,fn-1) = (fn-1+fn-2,fn-2)
     68 (fn-1,fn-2) = (fn-1,fn-2)*A
     69 .....
     70 (fn,fn-1) = (f1,f0)*A^(n-1).
     71 f1=1,f0=0,f2=1.
     72 只求fn,可以直接(fn,fn-1)
     73 之所以能logn就是因为求幂运算可以采用二分法。
     74 那么求数列的第n项就是等于求矩阵A的第n-1次幂,计算的速度非常快,时间复杂度为O(logn)。
     75 首先我们用long long 型表示数列中的元素,它只能表示20位的整数,能表示的范围太小,最多第92个元素。
     76 */
     77 
     78 void multiply(long long A[2][2],long long B[2][2],long long C[2][2])
     79 {
     80     //for(int i=0;i<2;i++)                      //这样是不行的,因为有覆盖问题,还真的必须拆开写
     81     //    for(int j=0;j<2;j++)
     82     //        for(int k=0;k<2;k++)
     83     //          C[i][j]+=A[i][k]*B[k][j];
     84     int tmp[4];
     85     tmp[0]=A[0][0]*B[0][0]+A[0][1]*B[1][0];
     86     tmp[1]=A[0][0]*B[0][1]+A[0][1]*B[1][1];
     87     tmp[2]=A[1][0]*B[0][0]+A[1][1]*B[1][0];
     88     tmp[3]=A[1][0]*B[0][1]+A[1][1]*B[1][1];
     89     C[0][0]=tmp[0];
     90     C[0][1]=tmp[1];
     91     C[1][0]=tmp[2];
     92     C[1][1]=tmp[3];
     93 }
     94 
     95 int fibnaq5(int n)   //采用矩阵方法的O(logn)
     96 {
     97     if(n<=0)
     98         return -1;
     99     if(n<=2)
    100         return 1;
    101     long long result[2][2]={{1,0},{0,1}};             //单位阵
    102     long long a[2][2]={{1,1},{1,0}};
    103     n=n-1;                    //注意n-1次方
    104     while(n)
    105     {
    106         if(n&1)
    107             multiply(result,a,result);
    108         multiply(a,a,a);
    109         n>>=1;
    110     }
    111     return result[0][0];             //因为(1,0)*result【2】【2】,为(fn,fn-1),fn=result【0】【0】。还是看编程之美才行啊
    112                                                 
    113 
    114 
    115 //a的n次方,迭代方法
    116 int pow(int a,int n)          //n必须是正的,否则移位死循环
    117 {
    118  int ans=1;
    119  while(n)
    120  {
    121   if(n&1)             //如果n是奇数如n=5,则首次乘以a,ans=a,则移位后一直是偶数,直到最后一次,n==1时,为奇数,又把最开始的a乘上了;如果开始n是偶数,则一直未a*=a,直到最后一次,乘以1.
    122                         //变成除以2也可以,但是不如移位好
    123    ans*=a;
    124   a*=a;
    125   n>>=1;
    126  // n/=2;                  //用n/=2,负数不会死循环,因为-1/2=0
    127  }
    128  return ans;
    129 }
    130 
    131 //递归求a的n次方
    132 int pow2(int a,int n)
    133 {
    134     if(n==1)
    135         return 1;
    136     if(n==1)
    137         return a;
    138     int tmp=pow2(a,n/2);
    139     if(n&1)
    140         return a*tmp*tmp;
    141     else
    142         return tmp*tmp;
    143 }
    144 
    145 
    146 int main()
    147 {
    148     int n;
    149     cin>>n;
    150     cout<<fibnaq4(n)<<endl;
    151     //cout<<pow2(2,4)<<endl;
    152     system("pause");
    153 }
  • 相关阅读:
    Linux
    springboot gateway 动态路由-01
    springboot远程debug调试
    springboot使用策略模式实现一个基本的促销
    springboot swagger2案例
    Tcp三次握手四次挥手个人学习
    springboot使用自定义注解和反射实现一个简单的支付
    java后端使用token处理表单重复提交
    基于redis实现未登录购物车
    java中的VO、PO、BO、DAO、POJO
  • 原文地址:https://www.cnblogs.com/zmlctt/p/3843854.html
Copyright © 2011-2022 走看看