斐波那契數列 題解

2021-07-06 03:58:53 字數 3641 閱讀 9572

原題出自ural 1133

題目大意:擴充套件斐波那契數列在整數集上的定義,即不是從f0

=0,f1=

1 這樣子開始的,下標可以是任意整數。給定這樣乙個序列中的兩個下標,i,j,以及他們在序列中對應的值fi

,fj ,然後要求fn

(n是輸入的乙個數字)。

思路1:由於題目裡說到資料範圍在 −2

∗109≤

fk≤2

∗109(

k=mi

n(i,

j,n)

,…,m

ax(i

,j,n

)).

所以可以考慮直接二分查詢fi

+1(在下面有分析)就好了(很容易驗證這個序列的單調性)。

思路2:觀察係數規律,i,j,n中的最小者是i,那麼: fi

+2=f

i+1+

fi, fi

+3=f

i+2+

fi+1

=2fi

+1+f

i , fi

+4=f

i+3+

fi+2

=3fi

+1+2

fi, … f

i+n=

fnfi

+1+f

n−1f

i . 其中f

n 是常規的斐波那契數列:,這個規律我稱之為「係數規律」。

現在只看i和j,假設j比i大,那麼: fi

,fi+

1,fi

+2,.

..,f

j ,有了「係數規律」,只需要求解fi

+1就好了,一旦知道了fi

+1,那麼就可以直接算出fn

了。怎麼算出n呢?假設n比i大,那麼根據上面推導的「係數規律」,有: fn

=fi+

(n−i

)=fn

−ifi

+1+f

n−i−

1fi.

所以關鍵是求出fi

+1,那麼怎麼求呢?還是根據「係數規律」!!!我們已知fi

和fj ,那麼就有: fj

=fi+

(j−i

)=fj

−ifi

+1+f

j−i−

1fi.

(1)

注意到方程(1)只有乙個未知數fi

+1,很容易求出: fi

+1=(

fi−f

j−i−

1fi)

/fj−

i.至此,貌似一切問題都解決了,不過還有兩個小問題:

1)如果n比i小?(反過來推就好了,知道fi

和fi+

1 之後)

2)需要預處理先求出斐波那契,但是這道題最多要計算到

f2000

,不會爆嗎?試試c++的long double咯,反正我過了,或者任性的,可以直接用python╮(╯▽╰)╭。

貼**如下:

#include 

using

namespace

std;

typedef

long

double ld;

const

int max = 2005;

ld f[max];

int main()

// 因為陣列的下標應該是非負的

i += 1000, j += 1000, n += 1000;

// 求出f(i+1)

fii = (j - i == 1) ? fj : ((fj - f[j-i-1]*fi) / f[j-i]);

if (n == i)

fn = fi;

else

if (n - i == 1)

fn = fii;

else

if (n - i > 1)

}else

}cout

<< (int)fn << endl;

return

0;}

執行結果是:

好吧,雖然有點醜,但我覺得還是把演算法說到位了。

最後再說一句,這道題這麼敏感的計算,再次演示了「編譯器有毒」系列作品,用visual c++ 2013的人目測都會死得很慘,因為我就是用它,然後一直wa 10了,改用g++ 4.9就好了╮(╯▽╰)╭。。。。。

最後再貼我用python 3的**(矩陣快速冪+二分):

# ural 1133

unit = [[1, 1], [1, 0]]

defmul

(a, b):

ans = [[0

for i in range(0, len(a))] for j in range(0, len(b))]

for i in range(0, len(a)):

for j in range(0, len(b)):

for k in range(0, len(b)):

ans[i][j] += a[i][k] * b[k][j]

return ans

defpow

(n):

'''注意不能寫n /= 2,會被python當做浮點數,應該是用位運算'''

a = unit

b = [[1, 0], [0, 1]]

while n > 0:

if n & 1:

b = mul(a, b)

a = mul(a, a)

n >>= 1

return b

defcal

(i, fi, j, fj, n):

mat = pow(j-1)

[left, right] = [int(-2*1e9), int(2*1e9)]

while left <= right:

mid = (left + right) >> 1

x = mat[0][0] * mid + mat[0][1] * fi

if x > fj:

right = mid - 1

elif x < fj:

left = mid + 1

else:

break

if n > 0:

mat = pow(n - 1)

print(mid*mat[0][0] + fi*mat[0][1])

else:

[fa, fb] = [mid, fi]

for i in range(n, 0):

[fa, fb] = [fb, fa - fb]

print(fb)

if __name__ == '__main__':

[i, fi, j, fj, n] = [int(i) for i in input().split(' ')]

if i > j:

[i, j] = [j, i]

[fi, fj] = [fj, fi]

j -= i

n -= i

i = 0

cal(i, fi, j, fj, n)

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

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

迴圈斐波那契數列 斐波那契數列應用

什麼是斐波那契數列 斐波那契數列指的是這樣乙個數列 1,1,2,3,5,8,13,21,34,55,89,144 這個數列從第3項開始,每一項都等於前兩項之和 台階問題 有一段樓梯有10級台階,規定每一步只能跨一級或兩級,要登上第10級台階有幾種不同的走法?這就是乙個斐波那契數列 登上第一級台階有一...

斐波那契數列

1 題目描述 大家都知道斐波那契數列,現在要求輸入乙個整數n,請你輸出斐波那契數列的第n項。斐波那契數列的定義如下 輸入 輸入可能包含多個測試樣例,對於每個測試案例,輸入包括乙個整數n 1 n 70 輸出 對應每個測試案例,輸出第n項斐波那契數列的值。2 這是九度上的乙個題,要求時間限制1秒,整數的...