矩陣乘法求fibo數列第n項(hihocoder第41周)
骨牌,一種古老的玩具。今天我們要研究的是骨牌的覆蓋問題:
我們有乙個2xn的長條形棋盤,然後用1x2的骨牌去覆蓋整個棋盤。對於這個棋盤,一共有多少種不同的覆蓋方法呢?
舉個例子,當n=1、2、3時
解法:對於骨牌覆蓋,我們可以考慮從已經覆蓋了一些骨牌的情況推廣到覆蓋更多骨牌的情況
最右邊的一種情況是不可能發生的,否則會始終多乙個格仔沒有辦法放置骨牌。或者說灰色部分的格仔數為奇數,不可能通過1x2個骨牌放置出來。
那麼通過對上面的觀察,我們可以發現:
在任何乙個放置方案最後,一定滿足前面兩種情況。而灰色的部分又正好對應了長度為n-1和n-2時的放置方案。由此,我們可以得到遞推公式:
f[n] = f[n-1] + f[n-2];
這個公式是不是看上去很眼熟?沒錯,這正是我們的費波拉契數列。[1]
因此,問題被轉化成為求斐波拉契數列第n項的問題。
對於數值較小的fibo數列,我們可以直接用遞迴求解:
int fibo(int x)
但是,對於數值較大的斐波那契數列,這種方法是無法完美處理的,因為fibo數列第100項的大小超過了long long的最大值 2^63-1。所以必須使用一種乘法來求解斐波那契數列的通項
因為乘法具有這樣乙個性質:
(a * b) mod n = ((a mod n) * (b * mod n)) mod n
因此,使用乘法處理斐波拉契數列的通項可以保證數值不越界。
實際上,對於線性遞推式,我們可以使用矩陣乘法來求解。對於斐波那契數列,我們希望找到乙個 2 * 2 的矩陣 m ,使得(a, b) x m = (b, a + b)
對於這樣乙個矩陣,我們可以設
m = [ x, y ; z, w]
得到方程
(a , b) x m = (a * x + b * z , a * y + b * w)
轉化為方程組
a * x + b * z = b;
a * y + b * w = a + b;
得到:
x=0;y=1;z=1;w=1;
因此
進一步可以知道:
那麼接下來的問題是,能不能快速的計算出m^n?我們先來分析一下冪運算。由於乘法是滿足結合律的,所以我們有:
不妨將k[1]..k[j]劃分的更好一點?
其中(k[1],k[2]...k[j])2表示將n表示成二進位制數後每一位的數字。上面這個公式同時滿足這樣乙個性質:
結合這兩者我們可以得到乙個演算法:
1. 先計算出所有的,因為該數列滿足遞推公式,時間複雜度為o(logn)
2. 將指數n二進位製化,再利用公式將對應的a^j相乘計算出a^n,時間複雜度仍然為o(logn)
則總的時間複雜度為o(logn)
這種演算法因為能夠在很短時間內求出冪,我們稱之為「快速冪」演算法。
#include #include #include #include #include #define mod 19999997
#define max 100000000
using namespace std;
/*int fibo(int x)
*/int to2(long long n, vector & k)
reverse(k.begin(), k.end());//其實這一步是脫褲子打屁
return 0;
}long long quick_fibo (long long n)
long long tmp_x = ((x % mod * x % mod) % mod + (y % mod * z % mod) % mod) % mod;
long long tmp_y = ((x % mod * y % mod) % mod + (y % mod * w % mod) % mod) % mod;
long long tmp_z = ((x % mod * z % mod) % mod + (w % mod * z % mod) % mod) % mod;
long long tmp_w = ((w % mod * w % mod) % mod + (z % mod * y % mod) % mod) % mod;
x = tmp_x;
y = tmp_y;
z = tmp_z;
w = tmp_w;
} return d;
}int main(void)
,快速乘,快速冪,矩陣快速冪 求斐波那契數列
快速冪 方法一 首先快速冪有幾個公式 1.a b mod c a mod c b mod c ab mod c a mod c b mod c mod c 積的取餘等於取餘的積取餘 快速冪演算法依賴於一下兩個公式 a b mod c a b 2 mod c b是偶數 a b mod c a b 2 ...
斐波那契(矩陣快速冪)
斐波那契數列,即fib n fib n 1 fib n 2 fib n fib n 1 fib n 2 fib n fib n 1 fi b n 2 就這麼乙個數列,顯然可以直接遞推求解,時間複雜度o n o n o n 似乎沒什麼問題。然後就遇到了這個,n nn的取值範圍最大是2 1 09 2 t...
矩陣快速冪求斐波那契數列
求數a aa的n nn次冪,可以採用二分法進行快速計算,即 a n a cdot a n為偶數 a cdot a cdot a n為奇數 end right.an a n a a a cdot a cdot a cdot a cdots a a cdot a cdot a cdot a 2 cdot...