感覺一天時間過得挺快,而自己卻沒有什么收獲。
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 }