斐波那契數列取模(大數)分治演算法
這是演算法課程上完分之策略後老師留的一道題目:
菲波那契數列如下: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的餘數
若不用遞迴,其實類似
實現**:
#includeusingnamespace 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 ...