斐波那契數列快速計算


感覺一天時間過得挺快,而自己卻沒有什么收獲。

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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM