日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2025/4/14 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 斐波那契数列取模(大数)分治算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
斐波那契數列取模(大數)分治算法

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

菲波那契數列如下: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 1?
1 1?
也就是說,如果我們要求第100個fibonacci數,只需要將矩陣?
[0,1]乘上?
0 1?
1 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的余數

若不用遞歸,其實類似

實現代碼:

#include<iostream> using 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==1){a=0;b=c=d=1;return ;}if(n%2==0){func(n/2,a,b,c,d);tempA=a*a+b*c;tempB=b*(a+d);tempC=c*(a+d);tempD=c*b+d*d;a=tempA%1997;b=tempB%1997;c=tempC%1997;d=tempD%1997;return;}else{func(n/2,a,b,c,d);tempA=b*(a+d);tempB=a*a+b*(a+c+d);tempC=c*b+d*d;tempD=c*(a+b+d)+d*d;a=tempA%1997;b=tempB%1997;c=tempC%1997;d=tempD%1997;return;} } int main(){int n;while(cin>>n&&n!=0){int a,b,c,d;if(n<=2){cout<<1<<endl;continue;}else n-=2;func(n,a,b,c,d);cout<<(b+d)%1997<<endl;} return 0; }

總結

以上是生活随笔為你收集整理的斐波那契数列取模(大数)分治算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。