斐波那契数列快速计算
Posted y119777
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了斐波那契数列快速计算相关的知识,希望对你有一定的参考价值。
感觉一天时间过得挺快,而自己却没有什么收获。
1.之前恰好看了跟快速幂乘法一样的计算大数乘法模,防止溢出,感觉挺有用的,而且用的挺多的。
2.分析问题的能力还很差,遇到一个问题,无法正确的进行转化,怎么进行考虑,感觉自己这方面还很欠缺,这应该是通过大量做题,然后不断总结得出来的吧!毕竟题做的多了,遇到新题也就那几种套路。感觉也是挺对的,面试题的那些小套路在搞竞赛的人面前根本什么也不是,感觉这句话挺有道理的。
3. 这次做的这道题,最后就是转化为求第n个斐波那契数,而我根本没有推导出这个。然后,之前做过怎么快速求解,一个是根据递推公式,还想是f(n)可以通过f(n/2),f(n/2 + 1), f(n/2 - 1)这几个数导出来,我也懒得记,遇到的时候就拿前几个数推导一下,很简单的。另一个方法,就是转移矩阵,快速幂求解。这个方法算是通用的方法(套路),大多数题,搞出来递推公式,可能转移条件比较多,然后搞成转移矩阵的形式,给出初始值,然后求第n个,就是求矩阵的n次幂,然后就是快速幂乘法。这个方法很重要。
4. 忘了,这次还有一点非常重要,就是leetcode上面house robber 那题,思路倒不是挺难,但是感觉自己写的代码很丑,然后今天遇到类似的转化,就很麻烦。然后看题解,得出一种巧妙的方法。题目要求不能出现连续的1,因为是环形的,要求第一个和最后一个不能同时是1,这就增加的复杂性,你不能简单的一次递推,然后考虑这样,枚举第一个位置是0,然后从第二个位置开始,随意放,可以放还可以不放,最后的答案就是最后一个放和不放的总和,第二种情况是:第一个放,那么第二个不能放,然后从第三个开始,可以随意放,然后就转化成前面的那个问题,而且不用重复计算,最后的答案就是最后一个不能放的个数,最终把这两种情况加起来就是最后的答案。这样代码写出来,看起来也特别整齐。仔细想想,真的很巧妙!
下面贴一下我写的求斐波那契:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 1e6 + 10; 5 const int mod = 1e9 + 7; 6 ll dp[maxn][2]; 7 ll n; 8 map<ll, ll> ma; 9 ll work(ll x) { 10 if(x == 0) return 1; 11 if(x < 4) return x; 12 if(ma.count(x)) return ma[x]; 13 ll res = 0; 14 ll t = x / 2; 15 if(x & 1) { 16 res = work(t) * (work(t - 1) + work(t + 1)) % mod; 17 } else { 18 res = work(t) * work(t) % mod + work(t - 1) * work(t - 1) % mod; 19 } 20 return ma[x] = res; 21 } 22 void solve() { 23 cin >> n; 24 ll res = (work(n) + work(n - 2)) % mod; 25 cout << res << endl; 26 } 27 int main() { 28 solve(); 29 /* Enter your code here. Read input from STDIN. Print output to STDOUT */ 30 return 0; 31 }
1 #include<bits/stdc++.h> 2 #define pb push_back 3 #define FOR(i, n) for (int i = 0; i < (int)n; ++i) 4 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 5 typedef long long ll; 6 using namespace std; 7 typedef pair<int, int> pii; 8 const int maxn = 1e3 + 10; 9 const int mod = 1e9 + 7; 10 struct mat { 11 ll a[4]; 12 void init() { 13 a[0] = a[3] = 1; 14 a[1] = a[2] = 0; 15 } 16 mat mul(const mat &x) { 17 mat res; 18 res.a[0] = (a[0] * x.a[0] % mod + a[1] * x.a[2] % mod) % mod; 19 res.a[1] = (a[0] * x.a[1] % mod + a[1] * x.a[3] % mod) % mod; 20 res.a[2] = (a[2] * x.a[0] % mod + a[3] * x.a[2] % mod) % mod; 21 res.a[3] = (a[2] * x.a[1] % mod + a[3] * x.a[3] % mod) % mod; 22 return res; 23 } 24 }; 25 mat pow(mat a, ll b) { 26 mat res; 27 res.init(); 28 while(b) { 29 if(b & 1) res = res.mul(a); 30 a = a.mul(a); 31 b >>= 1; 32 } 33 return res; 34 } 35 ll fb(ll n) { 36 if(n == 0) return 1; 37 if(n < 4) return n; 38 mat t; 39 t.a[0] = 0; t.a[1] = 1; t.a[2] = 1; t.a[3] = 1; 40 t = pow(t, n); 41 return t.a[3]; 42 } 43 ll n; 44 void solve() { 45 while(cin >> n) { 46 47 ll res = (fb(n) + fb(n - 2)) % mod; 48 cout << res << endl; 49 } 50 } 51 int main() { 52 //freopen("test.in", "r", stdin); 53 //freopen("test.out", "w", stdout); 54 solve(); 55 return 0; 56 }
以上是关于斐波那契数列快速计算的主要内容,如果未能解决你的问题,请参考以下文章
禅与计算机程序设计艺术使用 16 门编程语言实现斐波那契数列:循环控制指令与函数递归思想