快速幂--斐波那契数列

1)编写程序,求解a^b。其中b是正整数。

方法1.

//一般求幂算法,O(r)
    public static long power1(int a,int r){
        if(r<0) {
            System.out.println("r must be positive number!");
            return -1;
        }
        if(r==0){
            return 1;
        }
        long res=1;
        for(int i=1;i<=r;++i){
            res*=a;
        }
        return res;
    }

  这种使用连乘计算幂值的算法,复杂度是O(n)。不过如果将连乘拆分为若干相乘的表达式就可以减少做乘法的次数,自然也能提高算法效率。

方法2:快速幂计算

  以a^10为例,一般方法是a^10=a*a*a*a*a*a*a*a*a*a,做9次乘法操作。为了减少乘法操作次数,首先将指数以二进制形式表示,10的二进制形式为1010。就有a^10=a^(0*2^0+1*2^1+0*2^2+1*2^3)=a^(1*2^1+1*2^3)=(a^2)*((a^2)^3)=(a*a)*((a^2)*(a^2)*(a^2)),将乘法操作次数从9次减少为4次,复用了计算结果a^2。

  推导公式:ab=ap(n)*2^n+p(n-1)*2^(n-1)+...+p(0)*2^0=ap(n)*2^n*ap(n-1)*2^(n-1)*...ap(i)*2^i...*ap(0)*2^0,其中p(i)是对应的二进制位,如果是0,对应的项在计算的时候可以省略。另外有a^(2^i)=a^(2^(i-1)*2)=a^((2^(i-1))^2)。 

  快速幂的代码如下:

public static long quickPower(long A,int k){
        if(k<0){
            System.out.println("enter positive numbers");
            return -1l;
        }

        if(0==k){
            return 1;
        }
        long ans=1;
        while (k!=0){
            if(k%2==1){//二进制位是1
                ans*=A;
            }
            A*=A;
            k/=2;
        }
        return ans;
    }

   时间复杂度是O(log n)。

  递归求解幂运算的代码:

//递归幂计算,O(log r)

    public static long power2(int a,long r){
        if(r<0){
            System.out.println("enter positive numbers");
            return -1l;
        }
        if(0==r){
            return 1l;
        }
        boolean flag=false;
        if(0l==r%2l){
            flag=true;
        }
        long val=flag?r/2l:(r-1)/2l;
        if(flag){//偶数
            long cc=power2(a,val);
            return cc*cc;
        }
        else {//奇数
            long cc=power2(a,val);
            return a*cc*cc;
        }
    }

2)快速幂取模算法

  (a^b)%c=((a%c)^b)%c。快速幂取模算法是RSA算法的核心,其代码实现如下:

public static long quickPower(long A,int k,int m){
        if(k<0){
            System.out.println("enter positive numbers");
            return -1l;
        }

        if(0==k){
            return 1;
        }
        long ans=1;
        while (k!=0){
            if(k%2==1){//二进制位是1
                ans=(ans*A)%m;
            }
            A=(A*A)%m;
            k/=2;
        }
        return ans;
    }

3)使用矩阵快速幂求解斐波那契数列(https://www.zhihu.com/question/28062458)。代码如下:

 1   public static long fibonacci4(int k){
 2
 3         if(k==0){
 4             return 1;
 5         }
 6         long[][] c={{1,0},{0,1}};//单位矩阵,代替快速幂中的ans=1
 7         long[][] a={{1,1},{1,0}};//待求幂的矩阵,对应快速幂中的a
 8         while (k!=0){
 9             if(k%2!=0){
10                 c=multiply(c,a);
11             }
12             a=multiply(a,a);
13             k/=2;
14         }
15     return c[0][0]+c[0][1];
16
17     }
18
19     public static long[][] multiply(long[][] a,long[][] b){
20         long[][] c=new long[2][2];
21         c[0][0]=a[0][0]*b[0][0]+a[0][1]*b[1][0];
22         c[0][1]=a[0][0]*b[0][1]+a[0][1]*b[1][1];
23         c[1][0]=a[1][0]*b[0][0]+a[1][1]*b[1][0];
24         c[1][1]=a[1][0]*b[0][1]+a[1][1]*b[1][1];
25         return c;
26     }

  算法时间复杂度是O(log n),虽然包含矩阵乘法,不过,矩阵始终是2*2的方阵,并不会随着输入规模的增大而有所变化。

  另外三种方法求解斐波那契数列。

 1 //二分递归求斐波那契数列,将大问题需要拆分为两个子问题,然后分别通过递归调用求解,这就是二分递归。
 2     public static int fibonacci1(int k){
 3        return k<=1?k:(fibonacci1(k-1)+fibonacci1(k-2));
 4     }//O(2^k),利用斐波那契数列通项公式求得。大量重复计算
 5
 6     //线性递归。O(n)
 7     public static long[] fibonacci2( long k){
 8         if(k<=1){
 9             long[] intPairs=new long[2];
10             intPairs[0]=k;
11             intPairs[1]=0;
12             return intPairs;
13         }
14         long[] intPairs=fibonacci2(k-1);
15         long temp=intPairs[1];
16         intPairs[1]=intPairs[0];
17         intPairs[0]+=temp;
18         return intPairs;
19     }
20
21     //递推求解,O(n)
22
23     public static  long fibonacci3(long k){
24         if(k<=1){
25             return k;
26         }
27         long preValue1=0;
28         long preValue2=1;
29         long sum=0;
30         for(int i=2;i<=k;++i){
31             sum=preValue1+preValue2;
32             preValue1=preValue2;
33             preValue2=sum;
34
35         }
36         return sum;
37     }
时间: 2024-10-04 06:04:14

快速幂--斐波那契数列的相关文章

矩阵快速幂 斐波那契数列

#include<bits/stdc++.h> #define ll long long using namespace std; struct matrix{ll g[2][2];}; matrix mul(matrix a,matrix b){ matrix c; c.g[0][0]=c.g[0][1]=c.g[1][0]=c.g[1][1]=0; for(int i=0;i<=1;i++) for(int j=0;j<=1;j++) for(int k=0;k<=1;k

快速求斐波那契数列(矩阵乘法+快速幂)

斐波那契数列 给你一个n:f(n)=f(n-1)+f(n-2) 请求出 f(f(n)),由于结果很大请 对答案 mod 10^9+7; 1<=n<=10^100; 用矩阵乘法+快速幂求斐波那契数列是经典应用: 矩阵公式 C i j=C i k *C k j; 根据递推式 构造2*2矩阵: 原始矩阵 1 0 0 1 矩阵 2 1 1 1 0 原始矩阵与矩阵 2相乘达到转化状态效果: 对矩阵二进行快速幂 乘法:达到快速转化矩阵的效果: 即使达到快速转化状态:那么大的数据范围也很难求解: 高精?这有

矩阵的幂 斐波那契数列

题意: 斐波那契数列是由如下递推式定义的数列 F0 = 0 F1 = 1 Fn+2 = Fn+1 + Fn 求这个数列第n项的值对10000取余后的结果 输入: n = 10 输出: 55 #include <cstdio> #include <vector> using namespace std; //用二维vector来表示矩阵 typedef vector<int> vec; typedef vector<vec> mat; typedef long

快速求斐波那契数列&lt;黄金分割率&gt;

有一个固定的数学公式= =,不知道的话显然没法应用 a(n)为斐波那契数第n项 O(1)复杂度 Python def fib(self, N): golden_ratio = (1 + 5 ** 0.5) / 2 return int((golden_ratio ** N + 1) / 5 ** 0.5) 原文地址:https://www.cnblogs.com/shitianfang/p/12347963.html

【矩阵快速幂】HDU 4549 : M斐波那契数列(矩阵嵌套)

[题目链接]click here~~ [题目大意] M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗?对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行. [Source] :2013金山西山居创意游戏程序挑战赛――初赛(2) [解题思路] 这个题稍微有点难度,就

HDU 4549 M斐波那契数列(矩阵快速幂)

Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据: 每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 ) Output 对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模

hdu 4549 M斐波那契数列(快速幂 矩阵快速幂 费马小定理)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4549: 题目是中文的很容易理解吧.可一开始我把题目看错了,这毛病哈哈. 一开始我看错题时,就用了一个快速幂来解,不用说肯定wa,看题目的通过率也不高,我想会不会有啥坑啊.然而我就是那大坑,哈哈. 不说了,直接说题吧,先讨论k=1,2,3;时的解.这应该会解吧,不多说了: 从第四项开始f(4)=a^1+b^2;f(5)=a^2+b^3;f(6)=a^3+b^5......; 看出来了吧,a上的指数成斐波

#斐波那契数列用矩阵快速幂求解f(n)#

通常情况下,斐波那契数列第n项可以通过递归求解或者直接求解但当n非常大的时候,求解f(n)将显得非常困难下面利用矩阵以及快速幂的方法在logn复杂度内求解 则可以运用快速幂来求解矩阵高次幂,复杂度降为logn 来自为知笔记(Wiz)

poj 3070 Fibonacci (矩阵快速幂求斐波那契数列的第n项)

题意就是用矩阵乘法来求斐波那契数列的第n项的后四位数.如果后四位全为0,则输出0,否则 输出后四位去掉前导0,也...就...是...说...输出Fn%10000. 题目说的如此清楚..我居然还在%和/来找后四位还判断是不是全为0还输出时判断是否为0然后 去掉前导0.o(╯□╰)o 还有矩阵快速幂的幂是0时要特判. P.S:今天下午就想好今天学一下矩阵乘法方面的知识,这题是我的第一道正式接触矩阵乘法的题,欧耶! #include<cstdio> #include<iostream>