Fibonacci序列

[定理1] 標準Fibonacci序列(即第0項爲0,第1項爲1的序列)當N大於1時,一定有f(N)和f(N-1)互質

其實,結合“互質”的定義,和一個很經典的算法就可以輕鬆證明
對,就是輾轉相除法
互質的定義就是最大公約數爲1

數學歸納法是很有用的證明方法,我們接下來這個定理用數學歸納法就很好證明:
[定理2]若i爲奇數, f(i)*f(i)=f(i-1)*f(i+1)+1,否則f(i)*f(i)=f(i-1)*f(i+1)-1
對,這個定理用數學歸納法可以輕鬆證明,大家有興趣可以自己嘗試

[定理3] f(n)=f(i)*f(n-i-1)+f(i+1)*f(n-i)

f(n)=f(1)*f(n-2)+ f(2)*f(n-1)
    =f(2)*f(n-3)+ f(3)*f(n-2)
    =f(3)*f(n-4)+ f(4)*f(n-3)
看來沒有錯,證明方法就是這樣

這個公式也可以用來計算較大的fibonacci數除以某個數的餘數

設i=n/2 不過,爲了保證計算能延續下去 需要每次保留三個值
這樣,下一次計算就可以利用這三個值來求出兩個值,再相加就可以得到第三個值
譬如,計算出f(5),f(6),f(7),可以計算出f(11)、f(12),然後推出f(13)
就是剛纔洛奇的悲鳴(364738334)所提到的矩陣方法
我們知道我們若要簡單計算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的餘數

若不用遞歸,其實類似

http://acm.pku.edu.cn/JudgeOnline/problem?id=3070
這裏用的fib矩陣略有不同,是
f(n+1) f(n)
f(n) f(n-1)
但實際上可以驗證效果是一樣的

這題是要求求F(n)的最後四位數,所有乘法過程增加一個模10000的步驟即可,大家可以收藏稍候AC

關於矩陣我們告一段落,等下會回來繼續探討利用矩陣來解決複雜些的Fibonacci問題

http://acm.hdu.edu.cn/showproblem.php?pid=1568
我們來看這題,這題要求求出Fibonacci某項的前四位

當然,用矩陣也可以解決這道題——只要將乘法改爲乘並保留前四位

我們採用double 保留整數部分四位 這題最好還是double吧

不過顯然有更好的解法——如果我們知道Fibonacci序列的通項公式

F(n) = (((1+Sqrt(5))/2)^n - ((1-Sqrt(5))/2)^n)*1/Sqrt(5)

不過組合數學裏也有這一公式的推導方法 叫做“線性齊次遞推式”

這個解法的核心是,通解是某個數的冪 將f(n)=x^n代入遞推方程,可以解出三個通解 0和 (1+sqrt(5))/2

通常把“0”稱作平凡解,那麼特解就是通解的某個線性組合

再代入f(0)=0 f(1)=1,就可以得出我們剛纔的公式

不過通常情況下,我們只需要記住那個公式就可以了

提醒大家,記憶公式的時候千萬別忘記了係數1/sqrt(5)

因爲(1-sqrt(5))/2的絕對值小於1

所以當i較大的時候,往往可以忽略掉這一項
f(i)≈((1+Sqrt(5))/2)^n/sqrt(5);

所以,剛纔列舉出的HDOJ的1568,可以很簡單的30以內直接求解,30以上採用這個公式,還是用log(N)求冪的算法求解
恩,就是公式的前半部分

http://acm.hdu.edu.cn/showproblem.php?pid=1021
http://acm.zju.edu.cn/show_problem.php?pid=2060
Fibonacci某項是否被3整除

[定理5] 標準Fibonacci序列對任意大於2的正整數的餘數序列,必然是以“0 1”爲循環節開頭的序列

顯然0、1是序列開頭,也就是說序列開頭就是循環節開頭

循環長度的計算貌似是個比較難的問題,我一時還沒有想到有效解法,不過,要說明的是,計算複雜度時,這個循環節長度應該按複雜度O(N^2)計算

恩,證明方法是利用同餘定理、反證法,還有我們之前證明過的相鄰項一定互質的定理,留給大家家庭作業

http://acm.hdu.edu.cn/showproblem.php?pid=1588
這是前天比賽關於Fibonacci的一道題,大家先看看題。
Description看後半部分就行了

現在告訴大家一種正確解法,然後大家就可以去搞定這道題向別人炫耀了

首先,我們將問題整理一下,就是對等差數列 ai=k*i+b,求所有的f(ai)之和除以M的餘數

當0<=i<N

大家有沒有想到,因爲ai是等差數列,倘若f(ai)也是個等什麼序列,那說不定就有公式求了

f(ai)顯然不是等差數列,直接看上去也不是等比數列

但是如果把f(ai)換成我們剛纔所說的Fibonacci矩陣呢?

是的,可是我們對矩陣是直接求冪即可,由於矩陣加法的性質,我們要求A^ai的右上角元素之和,只要求A^ai之和的右上角元素

就矩陣這個東西來說,完全可以看作一個等比數列,
首項是:A^b
公比是:A^k
項數是:N

呵呵,我們可以把問題進一步簡化

因爲矩陣的加法對乘法也符合分配律,我們提出一個A^b來,形成這樣的式子:
A^b*( I + A^k + (A^k)^2 + .... + (A^k)^(N-1) )

A^b 和 A^k 顯然都可以用我們之前說過的方法計算出來,這剩下一部分累加怎麼解決呢

簡單起見,設A^k=B
要求 G(N)=I + ... + B^(N-1),設i=N/2
若N爲偶數,G(N)=G(i)+G(i)*B^i
若N爲奇數,G(N)=I+ G(i)*B + G(i) * (B^(i+1))

呵呵,這個方法就是比賽當時ACRush用的
而農夫用的則是更精妙的方法,大家可想知道

我們來設置這樣一個矩陣
B I
O I
其中O是零矩陣,I是單位矩陣

將它乘方,得到
B^2 I+B
O   I
乘三方,得到
B^3 I+B+B^2
O   I
乘四方,得到
B^4 I+B+B^2+B^3
O   I

既然已經轉換成矩陣的冪了,繼續用我們的二分或者二進制法,直接求出冪就可以了

http://online-judge.uva.es/p/v110/11089.html
大家來讀讀這一題

Fibinary數是指沒有相鄰的兩個1的二進制數。給N,求出第N大的Fibinary數

相對於二進制中每一位的值是2的冪,十進制中每一位的值是十的冪,
Fibonacci進制是每一位的值是對應Fibonacci數的一種計數系統。
     8 5 3 2 1
1     1
2     1 0
3     1 0 0
4     1 0 1
5     1 0 0 0
6     1 0 0 1
7     1 0 1 0
8     1 0 0 0 0
9     1 0 0 0 1
10   1 0 0 1 0
11   1 0 1 0 0
12   1 0 1 0 1
以上是前12個數字對應的十進制到Fibonacci進制的表格

Fibonacci的運算方法很奇怪。首先,它每一位上非0即1,而且不同於二進制的逢二進一或者十進制的逢十進一,它的進位方法是逢連續兩個1,則進1

譬如
1010110==> 1011000 ==> 1100000==>10000000

在最低位有個特殊情況,最低位既可以逢2進1,也可以和次低位一起逢相鄰進1
這種奇怪的進位方法,換句話描述就是,不存在兩個連續的1
因爲Fibonacci數其實也增長很快,int範圍內好像只有46個,本題只需要用最簡單的辦法轉換成Fibonacii進制即可
其中一題是
http://www.mydrs.org/program/down/ahoi2004day1.pdf
中的第二題,叫做數字迷陣
還有一題是PKU上的很出名的取石子問題
http://acm.pku.edu.cn/JudgeOnline/problem?id=1067

這題相當複雜,大家可以自己思考,往Fibonacci上想,也可以閱讀這裏的論文:
http://episte.math.ntu.edu.tw/articles/mm/mm_03_2_02/index.html
http://acm.pku.edu.cn/JudgeOnline/problem?id=2967

另外這題 可以利用Fibonacci判斷數據範圍進行優化設計。不過貌似可以水過去,僅僅給大家提供個思路罷

關於Fibonacci和黃金分割,還有很多更高明的結論和定理,希望大家也繼續討論,將自己的知識和他人共享
http://episte.math.ntu.edu.tw/articles/mm/mm_02_4_10/index.html
中例3詳細講述了用生成函數來計算Fibonacci數公式的運算過程。http://acm.hdu.edu.cn/showproblem.php?pid=1568
Fibonacci 求fibonacci前4位

http://acm.hdu.edu.cn/showproblem.php?pid=1588
Gauss Fibonacci
http://acm.pku.edu.cn/JudgeOnline/problem?id=1067
取石子問題
http://episte.math.ntu.edu.tw/articles/mm/mm_03_2_02/index.html 是報告
http://acm.pku.edu.cn/JudgeOnline/problem?id=3070
Fibonacci矩陣
http://acm.hdu.edu.cn/showproblem.php?pid=1021

http://acm.zju.edu.cn/show_problem.php?pid=2060
Fibonacci某項是否被3整除
http://acm.pku.edu.cn/JudgeOnline/problem?id=2116
Fibonacci進制計算
http://acm.pku.edu.cn/JudgeOnline/problem?id=2967
利用Fibonacci判斷數據範圍進行優化設計。
http://online-judge.uva.es/p/v110/11089.html
Fi-binary numbers,Fibonacci進制。
http://www.mydrs.org/program/down/ahoi2004day1.pdf
第二題 數字迷陣   這些,是今天涉及到的資料和網頁

轉至:http://www.cnblogs.com/Knuth/archive/2009/09/04/1559951.html

下面是一些題目的解題報告了,後面如果發現新的會補上來(不知道 FH算不算:-))
1. pku3070 Fibonacci
http://acm.pku.edu.cn/JudgeOnline/problem?id=3070
這個題目按照題意做就可以輕鬆的搞定了.問題關鍵是給出了我們另外一種求解Fibonacci的方法。利用矩陣乘法!
那爲什麼它就比遞推式和通項公式要好呢,原因是因爲Fibonacci的增長速度非常快,通常普通解法沒有辦法求得
後面的大數,所以題目通常要求取模,而如果用通項,肯定不夠精確了,用遞推公式又肯定會超時(比如要你求第1000000000個
Fibonacci數模10000000的最終結果),這個時候轉換爲求矩陣的冪次,可以在logn的時間內搞定.
我比較喜歡下面這個形式
|0 1|    |f(0)|                   |f(1)|
                         ===>   
|1 1|    |f(1)|                   |f(0)+f(1)| 後面這個也就是f(2)了
如果令 A爲那個0,1矩陣,可以發現
f(n) = (A^n).a12 * f(1) (a12爲右上角的元素值)
特別的 ,
A^0 = I (I是單位矩陣)

2. hdu1021 Fibonacci Again
http://acm.hdu.edu.cn/showproblem.php?pid=1021
通過一個模3障眼法,其實也可以使用上述的矩陣冪次進行求解.不過看題目的數據量,貌似直接用推倒也可以搞定

3. hdu1568
http://acm.hdu.edu.cn/showproblem.php?pid=1568
輸出一個fibonacci的前4個字母
這個要使用fibonacci的通項公式了
((1+√5)/2 )^n - ((1-√5)/2)^ n
--------------------------------
             √5 
可以發現後面的((1-√5)/2)^ n 當n很大的時候數值非常小,可以忽略,不會對前4位造成影響。
因此轉變爲了
((1+√5)/2 )^n
------------------
    √5 
這個式子隨着n的增長也是增長很快,但是我們可以發現,題目要求的是前4位,因此我們發現將長度固定在某個範圍
之內(即如果數大了,就除一下),這樣的話就可以取到前4位了.

4. hdu1250 Hat's Fibonacci
http://acm.hdu.edu.cn/showproblem.php?pid=1250
我用的赤裸裸的高精度算的把結果存起來了,大汗.內存佔了18M. Statistic裏面的貌似都很少的樣子.
後來我用數組去循環遞推做的,內存自然就下降下來了.這個題目貌似也可以構造矩陣,只不過要在計算
裏面處理好高精度.

5. hit1214 Fibonacci Coding
http://acm.hit.edu.cn/ojs/show.php?Proid=1214&Contestid=0
題目大意是去除相鄰的1,改變成前面一個.
我是直接模擬的,從高位開始判斷,如果相鄰位爲1且前面一個爲0,則變化,直至沒有出現該情況爲止
要注意的是,如果使用string,且在高位前產生進位的時候,要更新len,如果你沒有直接調用size的話.

6. hit1533 Fibonacci Numbers
http://acm.hit.edu.cn/ojs/show.php?Proid=1533&Contestid=0
高精度,與hdu1350類似

7. hit1864 Fibonacci
http://acm.hit.edu.cn/ojs/show.php?Proid=1864&Contestid=0
這個是求第k個finbonacci數的位數,求位數,用大數就太不明智了.
這裏我同樣的使用了通項的, 當n比較大的時候,利用變化過的通項
((1+√5)/2 )^n
---------------
    √5 
那麼求位數就用 log10(F) + 1
再利用log10(a*b) = log10(a) + log10(b), log10(a/b) = log10(a) - log10(b)

8. hit2060 Fibonacci Problem Again
http://acm.hit.edu.cn/ojs/show.php?Proid=2060&Contestid=0
大意求第a個到第b個之間所有fibonacci的數和。
這個有點小技巧在裏面,可以自己推導一下:
F(3) = F(1) + F(2)
F(4) = F(2) + F(3) = 1 * F(1) + 2 * F(2)
F(5) = F(3) + F(4) = 2 * F(1) + 3 * F(2)
F(6) = F(4) + F(5) = 3 * F(1) + 5 * F(2)
F(7) = F(5) + F(6) = 5 * F(1) + 8 * F(2)
F(8) = F(6) + F(7) = 8 * F(1) + 13 * F(2)

S(3) = 2 * F(1) + 2 * F(2)
S(4) = 3 * F(1) + 4 * F(2)
S(5) = 5 * F(1) + 7 * F(2)
S(6) = 8 * F(1) + 12 *F(2)
S(7) = 13 *F(1) + 20 *F(2)
不難發現,
S(n) = F(n + 2) - F(2)
因此題目就轉換爲了求 F(b + 2) - F(a + 2 - 1)
而又是大數取模,考慮使用矩陣求冪

9. hit2065 Fibonacci Number
http://acm.hit.edu.cn/ojs/show.php?Proid=2065&Contestid=0
赤裸裸的Fibonacci,最基本的那種

10. hit2204 Fibonacci Numbers
http://acm.hit.edu.cn/ojs/show.php?Proid=2204&Contestid=0
這個題目相當於求第k個Fibonacci的前4位和後4位,那麼前面的題目
綜合起來,就是前4位用通項,後4位用矩陣求模。
就不難了。要注意的是,前面求前4位的時候我用的O(n)的做法,過了。
這邊如果仍然採用O(n)的會TLE,必須採用O(logn),求冪次的方法才能過.

11. hit2255 Not Fibonacci
http://acm.hit.edu.cn/ojs/show.php?Proid=2255&Contestid=0
這個題目是個BT題,交了我n次,後來發現是s=0的時候負數情況沒有處理,汗.
粗看一下,這個題目和hit2060一樣,不過這裏好像都泛化了。這裏面的規律
可沒有上面那題那麼好找了。wy他們貌似直接推導S的公式,都是採用的什麼
等比數列弄的,我和felica討論了一下,發現了一個好的解法。通過構造分塊
矩陣,可以很好的解決這個問題。
首先構造
|0 1| |f(0)|
|q p| |f(1)|
這個可以利用矩陣冪次求得任何一個F(n),可惜這裏是求和,
那麼令A=前面那個p,q的矩陣
則S(n) = f(0) + f(1) + ... + f(n) = f(0) + (A + A^2 + ... + A^n)*F所得矩陣的右上角的值
那麼如何求得A + A^2 + ... + A^n呢
可以繼續構造如下的分塊矩陣,其中I是單位矩陣
|A I|
|0 I|
令R等於上面的矩陣,則
R^2 = |A^2   A*I + I|
      |0     I      |
R^3 = |A^3   A^2 * I + A * I + I|
      | 0     I                 |
可以發現右上角即爲I + A + A^2 + ... + A^n,多個I後面給減掉就可以了
這樣我們同樣可以再次利用矩陣冪次求得R^n
則S(n) = ((R^(n+1).m12 - I) * F).a12 + f(0)
可以很完美的解決這個問題.

12. hnu10072 Fibonacci Number
http://acm.hnu.cn:8080/online/?action=problem&type=show&id=10072&courseid=0
與hit2065一樣

13. tju1208 Fibonacci Numbers 
http://acm.tju.edu.cn/toj/showp1208.html
與hit1533一樣

14. zju2060 Fibonacci Again
http://acm.zju.edu.cn/show_problem.php?pid=2060
與hdu1021一樣

15. zju1828 Fibonacci Numbers
http://acm.zju.edu.cn/show_problem.php?pid=1828
與hit1533一樣

16. zju2672 Fibonacci Subsequence
http://acm.zju.edu.cn/show_problem.php?pid=2672

又是一道bt題,時間卡的非常之緊.
這個題目我使用的dp+hash.
記d(i,j)爲以第i個數作爲結尾,前一個數是第j個的fibonacci串的最大長度
則 d(i,j) = max{d(j, i - j)} + 1,
注意查找data[i] - data[j]的時候利用hash查找到的應該是j小的所有當中最大下標的那個。
因此需要在每次循環結束的時候更新已存在的數的hash。


17. hzu1060 Fibonacci數列
http://acm.fzu.edu.cn/problem.php?pid=1060
與hit1533相同

18. fjnu1158 Fibonacci數列
http://acm.fjnu.edu.cn/show?problem_id=1158
與hit1533相同

19. zjut Fibonacci數
http://acm.zjut.edu.cn/ShowProblem.aspx?ShowID=1029
與hit2065一樣,題目描述稍有不一樣


總結一下,主要能夠考察的是
1. 求解Fibonacci的某一項(這個範圍一般在45之內)
2. 求解Fibonacci的某一項模K(這個一般是大數),通用解決方法是構造矩陣求冪次
3. 求解Fibonacci的前多少位 (這個一般是大數), 通用解法是使用通項公式
4. 求解Fibonacci的後多少位,這個和取模類似
5. 求解Fibonacci的前n項和,利用推導式, S(n) = F(n + 2) - F(2)即可
6. 更多的是基於Fibonacci的綜合題,包括DP,構造,等等.

=======================================================
另外,gardon補充了一題:
就普通的f(0)=0,f(1)=1,f(n)=f(n-1)+f(n-2) 
給數列an=k*n+b
保證k>0,b>=0 
求1到n的f(an)之和 
輸入k、b、m,求出那個和模m的值 
b, m, n數的範圍都是10^9以內 
k <=20 
這個題目仍然可以使用hit那個BT題的做法。先構造矩陣
應該是
0 1
1 1的冪次了(主要是使得F'(n + 1) = F'(n)*矩陣),然後構造求和矩陣就可以了.

矩陣的方法。

思想來源上上次PKU的acm warmup
http://acm.pku.edu.cn/JudgeOnline/problem?id=3070

{{F(n+1),F(n)},
{F(n),F(n-1)}}

=

{{1,1}      ^n
{1,0}}

我當時就想,用加法算都只能是O(n)的,換成n個矩陣的連乘不是更廢勁嗎?其實不然,乘法方法有比加法更好的性質,用加法只能利用前兩個的值,而乘法卻不同,因爲乘法有結合律,可以大幅度下降算法的耗時。

令A(n)表示一個矩陣序列

A(n)=

{{F(n),F(n-1)},
{F(n-1),F(n-2)}

那麼A(2)={{1,1},{1,0}},由那個表達式得到:

A(n)=A(2)^(n-1),A(2)是己知的2*2矩陣,現在的問題就是如何求

A(2)^n

因爲方陣的乘法有結合律,所以

A(2)^n=A(2)^(n/2)*A(2)^(n/2),不妨設n是偶數

所以求A(n)就可以化成求A(n/2)並作一次乘法,所以遞歸方程是:

T(n)=T(n/2)+O(1)

它的解是O(lbn),不可思議吧。

最後我們要觀察這樣的矩陣方法可否推廣到一般情形,我們暫且稱這樣的遞推序列爲‘c階線性遞推方程’吧,它的意思就是說F(n)由與n相距c遠的前面的一些F(m)組成的線性組合,比如Fibonacci數列的最大距離就是2,所以這樣的遞推式需要確定一個序列至少要知道最初的c個己知初值,我們的目的就是要求這樣的遞歸式的一般算法:

F(n)={F(n-1),F(n-2),...F(n-c)}*K
{F(1),F(2),,,F(c)}^T=C

其中K={x1,x2,...xc}^T,C={c1,c2,...cc}^T都是非0的常向量。

我們構造A(n)表示一個c*c的矩陣序列,且形式爲

A(n)=

{{F(n),F(n-1),F(n-2),...F(n-c+1)},
{F(n-1),F(n-2),F(n-3),...F(n-c)},
......
{F(n-c+1),F(n-c),F(n-c-c),...F(n-2c+2)}}

爲了使它有意義,n-2c+2>=1,所以n>=2c-1,所以A(n)的初始矩陣是A(2c-1),可以按遞歸式直接構造它,然後我們考慮A(n)的生成矩陣會是什麼樣子,設爲G,於是應滿足:

A(n)=A(n-1)G

觀察A(n-1)的第一行,它剛好就是{F(n-1),F(n-2),...F(n-c)},由遞推式,知G的第一列應爲K,而第二列設爲x,則要滿足{F(n-1),F(n-2),...F(n-c)}x=F(n-1),很簡單,x={1,0,0,...},同樣第三列是{0,1,0,0,...},所以右邊應該是一個(c-1)*(c-1)的單位矩陣I再在最下面補上一行0,於是G可以表示爲:

G={K,{I,0}^T}

於是A(n)的通項就是

A(n)=A(2c-1)*G^(n-2c+1)

比如Fibonacci數列的K={1,1}^T,所以
G={K,{I,0}^T}=
{{1,1},
{1,0}}

再舉一個例子,也是以前做過的一個題,母牛生小牛的題,在一個農場上有很多母牛,第1年有一隻母牛,而且每過4年,母牛會開始生小母牛,小母牛過4年後也會開始生,此後就每年生一隻小母年,問第n年時有多少隻母牛?

簡單例出前幾個數字:1,1,1,2,3,4,6,。。。會發現一個規律,就是第n年的母牛數F(n)恰等於前一年的母牛數F(n-1),以及前三年的母牛數F(n-3)之和,其實直接得到這個遞推式也不難,因爲F(n-3)到F(n)剛好4年(第4年),所以F(n-3)都是一些可以生仔的牛數,它們會添加F(n-3)個小牛,同時F(n-1)是所有的牛媽媽,那當然有F(n)=F(n-1)+F(n-3)。

它的K={1,0,1},c=3,生成矩陣G=
{{1,1,0},
{0,0,1},
{1,0,0}}

所以有A(n)=A(3)*G^(n-2)

A(3)=
{{1,1,1},
{1,1,0},
{1,0,0}}

從O(2^n)到O(n),再到O(lbn),效率提高得也太猛烈了,不過一點要提出來,不管什麼樣的算法,Fiboacci數列本身數值的遞增是指數型的,所以要想算很高階的結果,也近乎不太可能,所以經常會在一個模數範圍內考慮。

 

F(2*n)=sigma(C(n,k)F(k)) k>=0,k<=n

 

 timus ural 1133. Fibonacci Sequence

http://acm.timus.ru/problem.aspx?space=1&num=1133 

複製代碼
import java.io.BufferedInputStream;
import java.math.BigInteger;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        int nmax = 2002, i, ii, jj, kk, temp;
        BigInteger ni, nii, nj, tempn;
        BigInteger[] fib0 = new BigInteger[nmax];
        BigInteger[] fib1 = new BigInteger[nmax];
        fib0[0] = BigInteger.ONE;
        fib0[1] = BigInteger.ZERO;
        fib1[0] = BigInteger.ZERO;
        fib1[1] = BigInteger.ONE;
        for (i = 2; i < nmax; i++) {
            fib0[i] = fib0[i - 1].add(fib0[i - 2]);
            fib1[i] = fib1[i - 1].add(fib1[i - 2]);
        }
        while (cin.hasNext()) {
            ii = cin.nextInt();
            ni = cin.nextBigInteger();
            jj = cin.nextInt();
            nj = cin.nextBigInteger();
            kk = cin.nextInt();
            ii += 1000;
            jj += 1000;
            kk += 1000;
            if (ii > jj) {
                temp = ii;
                ii = jj;
                jj = temp;
                tempn = ni;
                ni = nj;
                nj = tempn;
            }
            if (ii == jj - 1) {
                nii = nj;
            } else {
                nii = nj.subtract(ni.multiply(fib0[jj - ii])).divide(
                        fib1[jj - ii]);
            }
            if (kk == ii) {
                System.out.println(ni);
            } else if (kk == ii + 1) {
                System.out.println(nii);
            } else {
                if (kk > ii) {
                    ii++;
                    while (ii < kk) {
                        tempn = ni.add(nii);
                        ii++;
                        if (ii == kk) {
                            System.out.println(tempn);
                            break;
                        }
                        ni = nii;
                        nii = tempn;
                    }
                } else {
                    while (ii > kk) {
                        tempn = nii.subtract(ni);
                        ii--;
                        if (ii == kk) {
                            System.out.println(tempn);
                            break;
                        }
                        nii = ni;
                        ni = tempn;
                    }
                }
            }
        }
    }
}
發佈了31 篇原創文章 · 獲贊 21 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章