求斐波那契数列的多种方法(有矩阵(附好模板))
2017-08-09 21:31
288 查看
f[1]=1; f[2]=2; f
=f[n-1]+f[n-2];
(1)递推
(2) 循环
(3)矩阵乘法(空间换时间)【可取模哦】
数列的递推公式由矩阵乘法表示为
进一步,可得
那我们如何计算[1110]的(n−2)次方?
假设计算A的n次幂:
二阶矩阵的乘法满足结合律:A(BC)=(AB)C
法一:
令n=N/2;
1.若n为偶数,则A^N=A^n * A^n
2.若n为奇数,则A^N=A^n * A^n * A
举例:A^6=A^3 * A^3
A^7=A^3 * A^3 * A
法二:
“二进位为1需要乘,为0不需要乘”
以计算A^6为例:
A^6=A^4 * A^2
将6转换成二进制:110
第2位为1,需要乘,乘2^2(即A^4); 第1位还为1,需要乘,乘2^1(即A^2); 第0位为0,不需要乘。
即:若需要乘,则乘2^pos.
十进制7 = 二进制 111
则A^7=A^4∗A^2∗A^1
(4) 直接上公式……
=f[n-1]+f[n-2];
(1)递推
long long fib(int n) { if(n==1) return 1; if(n==2) return 2; return fib(n-1)+fib(n-2); }
(2) 循环
long long fib(int n) { long long a=1,b=2,c; if(n==1) return 1; if(n==2) return 2; for(int i=3;i<=n;i++) { c=a+b; a=b;b=c; } return c; }
(3)矩阵乘法(空间换时间)【可取模哦】
数列的递推公式由矩阵乘法表示为
进一步,可得
那我们如何计算[1110]的(n−2)次方?
假设计算A的n次幂:
二阶矩阵的乘法满足结合律:A(BC)=(AB)C
法一:
令n=N/2;
1.若n为偶数,则A^N=A^n * A^n
2.若n为奇数,则A^N=A^n * A^n * A
举例:A^6=A^3 * A^3
A^7=A^3 * A^3 * A
//使用模板前需先分析f[2]=1还是2!!!!!!!!!!!!!!!!!!!!!(这里f[2]=1) void multiply(int c[2][2],int a[2][2],int b[2][2],int mod) { int tmp[4]; tmp[0]=a[0][0]*b[0][0]+a[0][1]*b[1][0]; tmp[1]=a[0][0]*b[0][1]+a[0][1]*b[1][1]; tmp[2]=a[1][0]*b[0][0]+a[1][1]*b[1][0]; tmp[3]=a[1][0]*b[0][1]+a[1][1]*b[1][1]; c[0][0]=tmp[0]%mod; c[0][1]=tmp[1]%mod; c[1][0]=tmp[2]%mod; c[1][1]=tmp[3]%mod; }//计算矩阵乘法,c=a*b int fibonacci(int n,int mod)//mod表示数字太大时需要模的数 { if(n==0)return 0; else if(n<=2)return 1;//这里表示第0项为0,第1,2项为1 int a[2][2]={{1,1},{1,0}}; int result[2][2]={{1,0},{0,1}};//初始化为单位矩阵 int s; n-=2; while(n>0) { if(n%2 == 1) multiply(result,result,a,mod); multiply(a,a,a,mod); n /= 2; }//二分法求矩阵幂 s=(result[0][0]+result[0][1])%mod;//结果 return s; }
法二:
“二进位为1需要乘,为0不需要乘”
以计算A^6为例:
A^6=A^4 * A^2
将6转换成二进制:110
第2位为1,需要乘,乘2^2(即A^4); 第1位还为1,需要乘,乘2^1(即A^2); 第0位为0,不需要乘。
即:若需要乘,则乘2^pos.
十进制7 = 二进制 111
则A^7=A^4∗A^2∗A^1
////使用模板前需先分析f[2]=1还是2!!!!!!!!!!!!!!!!!!!!!(这里f[2]=2) ///求解fac(n)%100000,其中n为大于等于3的正整数 #include<stdio.h> #include<math.h> long long fac_tmp[6][4]={ ///存放矩阵次幂 ///位置:00 01 10 11 {24578,78309,78309,46269}, ///32次幂%100000 {1597,987,987,610}, ///16次幂%100000 {34,21,21,13}, ///8次幂%100000 {5,3,3,2}, ///4次幂%100000 {2,1,1,1}, ///2次幂%100000 {1,1,1,0}, ///1次幂%100000 }; void fac(int); int main() { int n; scanf("%d",&n); fac(n); return 1; } void fac(int k) ///k>=3 { int i; long long t00=1,t01=1,t10=1,t11=0; ///表示矩阵的1次幂 long long a,b,c,d; k=k-3; ///公式中是n-2次幂,(t00,t01,t10,t11)表示1次幂。所以一共减3次 for(i=k;i>=32;i=i-32) ///对于大于等于32的k; { a=(t00*fac_tmp[0][0]+t01*fac_tmp[0][2])%100000; b=(t00*fac_tmp[0][1]+t01*fac_tmp[0][3])%100000; c=(t10*fac_tmp[0][0]+t11*fac_tmp[0][2])%100000; d=(t10*fac_tmp[0][1]+t11*fac_tmp[0][3])%100000; t00=a; t01=b; t10=c;t11=d; } i=4; while(i>=0) ///对于小于32的k(16,8,4,2,1); { if(k>=(long long)pow(2,i)) ///如果k大于某一个2的次幂 { a=(t00*fac_tmp[5-i][0]+t01*fac_tmp[5-i][2])%100000; ///(5-i):矩阵的2的i次幂在数组fac_tmp中的位置为fac_tmp[5-i] b=(t00*fac_tmp[5-i][1]+t01*fac_tmp[5-i][3])%100000; c=(t10*fac_tmp[5-i][0]+t11*fac_tmp[5-i][2])%100000; d=(t10*fac_tmp[5-i][1]+t11*fac_tmp[5-i][3])%100000; t00=a; t01=b; t10=c;t11=d; k=k-(int)pow(2,i); } i--; } a=(t00*2+t01*1)%100000; printf("%lld\n",a); }
(4) 直接上公式……
相关文章推荐
- java 工厂+策略+模板方法模式实现单接口多种类型文件解析
- 51nod 巨大的斐波那契数列(矩阵快速幂),递推式优化的好模板!!!!!!!
- 斐波那契数列的第N项(矩阵快速幂模板)
- 剑指offer——斐波那契数列多种方法实现
- 斐波那契数列F(n)【n超大时的(矩阵加速运算) 模板】
- MOOC清华《面向对象程序设计》第5章:填充数字矩阵-终极中文版 v 3.0(采用模板方法,并增加集中控制功能)
- 矩阵连乘求斐波那契数列模板
- 洛谷 P1939 【模板】矩阵加速(数列):优化递推式的方法——矩阵快速幂
- 模板文件不存在,无法解析文档!-dede报错解决方法
- Android设计模式系列--模板方法模式
- 189. Rotate Array(再来多种方法)
- css自适应宽度 多种方法实现宽度自适应的水平居中
- jquery操作select下拉框的多种方法(选中,取值,赋值等)
- 设计模式C++学习笔记之九(Template Method模板方法模式)
- 大话设计模式学习(八)——模板方法模式
- 模板方法模式
- 4.模板方法模式
- C#操作excel(多种方法比较)
- c++设计模式:模板方法模式(Template Method Pattern)
- GOF之模板方法模式