斐波那契數列取模(大數)分治演算法

2021-09-01 16:44:11 字數 1439 閱讀 8746

斐波那契數列取模(大數)分治演算法

這是演算法課程上完分之策略後老師留的一道題目:

菲波那契數列如下:1,1,2,3,5,8,13,21,34......其中a[1] = 1, a[2] = 1, a[n]=a[n-1]+a[n-2](n>=3)。對給定的下標n,求解a[n]%1997的值.

其中測試資料n是整數範圍內。

這個題目,主要是用到很關鍵的乙個數學知識,斐波那契數列的求法,可以轉換為矩陣的連乘,矩陣的n此方演算法又可以用分治的演算法。

而且又有理論依據:(n*m)%c=[ (n%c)*(m%c) ]%c ; (n+m)%c=[ (n%c)+(m%c) ]%c ,所以過程中的結果可以隨時取模,而不影響最終的結果

關於斐波那契數列的矩陣連乘求法如下:

我們知道我們若要簡單計算f(n),有一種方法就是先儲存

a=f(0),b=f(1),然後每次設:

a'=b b'=a+b

並用新的a'和b'來繼續這一運算

如果大家熟悉利用「矩陣」這一工具的話,就知道,如果把a、b寫成乙個向量[a,b],完成上述操作相當於乘以矩陣

0 11 1

也就是說,如果我們要求第100個fibonacci數,只需要將矩陣

[0,1]乘上

0 11 1

的一百次方,再取出第一項

因為我們知道,矩陣運算滿足結合律,一次次右乘那個矩陣完全可以用乘上那個矩陣的n次方代替,更進一步,那個矩陣的n次方就是這樣的形式:

f(n-1) f(n)

f(n) f(n+1)

而求矩陣的n次方,由於矩陣乘法滿足結合律,所以我們可以用log(n)的演算法求出——這個演算法大家都會麼?

乙個是二分,乙個是基於二進位制的求冪

二分的原理:要求矩陣的n次方a(n),設i=n/2若n%2==1, 則 a(n)=a(i)*a(i)*a(1)若n%2==0, 則 a(n)=a(i)*a(i)

基於二進位制的原理:將n拆為二進位制數,譬如13=1101那麼 a^13= a^8 * a^4 * a^1 (這裡^表示冪運算)

也就是說,由a^1開始,自乘得到a^2,然後自乘得到a^4,如果n對應位為1,則將這個結果乘到目標上去

這樣的話,將所有乘法改為模乘,就可以得到乙個較大fibonacci數除以m的餘數

若不用遞迴,其實類似

實現**:

#includeusing

namespace std;

//f(n)=f(i)*f(n-i-1)+f(i+1)*f(n-i)

int tempa,tempb,tempc,tempd;

void func(int n,int &a,int &b,int &c,int &d)

if(n%2==0)

else

}int main()

else n-=2;

func(n,a,b,c,d);

cout<

0;}

HPU 1471 又是斐波那契數列??(大數取模)

時間限制 1 sec 記憶體限制 128 mb 提交 278 解決 27 統計 現在給你乙個數x,聰明的你一定知道這是斐波那契數列中的第幾項。資料保證x一定有對應的項y,且 0 y 第一行乙個整數t,表示測試組數。之後的t行,每行乙個數x 對於每個測試資料,輸出一行表示數x是第幾項 給出乙個數,求是...

HPU 1471 又是斐波那契數列??(大數取模)

時間限制 1 sec 記憶體限制 128 mb 提交 278 解決 27 統計 現在給你乙個數x,聰明的你一定知道這是斐波那契數列中的第幾項。資料保證x一定有對應的項y,且 0 y 第一行乙個整數t,表示測試組數。之後的t行,每行乙個數x 對於每個測試資料,輸出一行表示數x是第幾項 2 253 5給...

斐波那契數列 斐波那契數列python實現

斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家列昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 1 1 2 3 5 8 13 21 34 在數學上,斐波納契數列以如下被以遞推的方法定義 f 1 ...