1. 程式人生 > >【轉】斐波那契數列取模(大數)分治演算法

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


此中測試資料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的餘數


若不消遞迴,其實類似

相關推薦

數列大數分治演算法

此中測試資料n是整數侷限內。 這個題目,主如果用到很關鍵的一個數學常識,斐波那契數列的求法,可以轉換為矩陣的連乘,矩陣的n此方演算法又可以用分治的演算法。 並且又有理論根據:(n*m)%c=[ (n%c)*(m%c) ]%c ; (n+m)%c=[ (n%c)+(m%c) ]%c ,所以過程中的成果可以

數列大數分治演算法

這是演算法課程上完分之策略後老師留的一道題目: 菲波那契數列如下: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是整數範圍內。 這個題目,主要

數論數列求和公式

斐波那契數列: F(n)=F(n-1)+F(n-2); 其中,      F1=1, F2=1. 斐波那契數列求和公式:          Sn  =     2F(n)  +  F(n-1) -  1 Sn  =   F1 + F2 + F3 +……+ 

C++數列前N項的和遞迴與非遞迴演算法

定義:斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:0、1、1、2、3、5、8、1

Java數列前N項(堆疊演算法)

堆疊是一種很靈活的"後進先出"資料結構,使用堆疊可以節省記憶體的開銷。比如,遞迴是一種很消耗記憶體的演算法,可以藉助堆疊消除大部分遞迴,達到和遞迴演算法同樣的目的。 下面用例子實現求斐波那契數列前N項

Parity check 數列 n(0≤n≤) in

I - Parity check Crawling in process... Crawling failed Time Limit:2000MS     Memory Limit:524288KB     64bit IO Format:%lld & %llu

數列談矩陣1

斐波那契序列 集錦 (轉) [定理1] 標準Fibonacci序列(即第0項為0,第1項為1的序列)當N大於1時,一定有f(N)和f(N-1)互質 其實,結合“互質”的定義,和一個很經典的演算法就可以輕鬆證明  對,就是輾轉相除法  互質的定義就是最大公約數為1 數學

演算法 in python | DP數列vs卡塔蘭數列

1. 斐波那契數列 公式: 應用:爬樓梯 假設你正在爬樓梯。需要 n 階你才能到達樓頂。每次你可以爬 1 或 2 個臺階。你有多少種不同的方法可以爬到樓頂呢? class Solution: def climbStairs(self, n):

劍指offer數列非遞迴求解第N項

public class Solution {    public int Fibonacci(int n) {       //錯誤輸入處理       if

劍指offer數列非遞歸求解第N項

非遞歸 acc 斐波那契 錯誤 bsp fibonacci 更新 off for public class Solution { public int Fibonacci(int n) { //錯誤輸入處理 if(n<0) return

劍指offer第七題數列

題目描述 大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項為0)。 n<=39 剛開始覺得輸入為一個數,然後找到這個數在斐波那契數列中的位置

hdu4549 M數列矩陣快速冪F[n] = F[n-1] * F[n-2] ,求F[n]

【連結】 【題意】 F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 給出a, b, n,求出F[n] 【分析】 寫出幾項後,發現:F[n]=a^x*b^y,x,y成斐波那契數列。 且有規律:ans=a^

劍指offer{7-10}數列、跳臺階、變態跳臺階、矩形覆蓋

斐波那契數列、跳臺階、變態跳臺階、矩形覆蓋題目描述C++程式碼跳臺階題目描述C++程式碼變態跳臺階題目描述C++程式碼矩形覆蓋題目描述C++程式碼 注:思路均是動態規劃,用中間陣列dp存放計算值,如果

JZOJ-senior-4627. NOIP2016提高A組模擬7.15數列

Time Limits: 1000 ms Memory Limits: 524288 KB Description Input Output Sample Input 5 10 Sample O

程式設計5數列 + 遞迴+LeetCode50

傳送門:https://leetcode-cn.com/problems/powx-n/ 一、LeetCode 50. Pow(x, n) 1、題目描述 實現 pow(x, n) ,即計算 x 的 n 次冪函式。 2、示例 示例 1: 輸入: 2.00000, 1

劍指offer數列 遞迴 迴圈 時間 c++

題目:大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項為0)。n<=39 思路:可以用兩種方法實現,這裡遞迴的辦法因為有太多重複的計算會超時(計算n=39,需要4s左右,題目要求1s),遂改用迴圈語句寫(經測試n=39時,完全小於1s),下面的程式碼中也給

C語言數列的兩種演算法迴圈,遞迴

#include<stdio.h> int Fabio(int n) //迴圈 { int i; int f1 = 1; int f2 = 1; int f3 = 1; for(i = 2;i<n;i++) { f3 = f1 + f

題10 數列

演算法和資料操作 • 遞迴和迴圈: 很多演算法可以用遞迴和迴圈兩種不同方式實現。 通常基於遞迴的實現方法程式碼會比較簡潔,但效能不如基於迴圈的實現方法。 • 排序和查詢: 重點掌握二分查詢,歸併排序和快速排序。 例 題11旋轉陣列的最小數字 • 回溯法: 要求在二維陣列(迷宮或棋盤)上搜索路

遞迴演算法 數列的備忘錄優化

遞迴演算法之斐波那契數列的優化 閒來無事嘗試了一下斐波那契的遞迴演算法 遞迴的斐波那契數列的演算法的效率驚人的低 得到43個數據需要8秒鐘 而優化過帶備忘錄的斐波那契數列,只需要0.2秒就可以打出64個數據 2秒可打出1000個 說明了線性

劍指offer 數列問題

1、斐波那契數列 (Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:1、1、2、3、5、8、13、21、34、……在