寝癖頭の解法

学習中の覚え書きを投稿、更新していきます。

フィボナッチ数列について

フィボナッチ数列についての話です。
きっかけは、AIZU ONNLINE JUDGEのALDS1_10_Aから、"Fibonacci Number"の出題でした。
https://onlinejudge.u-aizu.ac.jp/problems/ALDS1_10_A

まずはフィボナッチ数について、Wikipediaによれば...
>イタリアの数学者レオナルド・フィボナッチ(ピサのレオナルド)に因んで名付けられた数である。
>フィボナッチ数は自然界の現象に数多く出現する。
>また、フィボナッチ数列が生み出す螺旋は、世界で最も美しい螺旋だと言われている。
例えば、植物の花や実の螺旋の数に多く現れて、葉の付き方などにも関連しているのだそうです。
ja.wikipedia.org
>フィボナッチは、近代では主に次のような業績で知られている。
>13世紀初頭に、『算盤の書』の出版を通じてアラビア数字のシステムをヨーロッパに導入した。
>自身で発見したわけではないが、『算盤の書』の中で例として紹介したことで、「フィボナッチ数列」に名前を残した。
ん? ちょっと待って、えーっと...「フィボナッチ数列は、インドの数学者の間では6世紀頃から知られていたが、西洋に初めて紹介したのはフィボナッチの書いた算盤の書である」ってことらしいです、なんか、モヤるけれど。
とりあえず進めます。

次に、フィボナッチ数列について...
>フィボナッチ数列(フィボナッチすうれつ、(英: Fibonacci sequence) (Fn) は、次の漸化式で定義される:
f:id:neguse_atama:20210930013902p:plain
>1202年にフィボナッチが発行した『算盤の書』(Liber Abaci) に記載されたことで「フィボナッチ数」と呼ばれているが、それ以前にもインドの学者であるヘーマチャンドラ (Hemachandra) が韻律の研究により発見し、書物に記したことが判明している。
なるほど、こうゆうことだったみたいです。

続いて、一般項について...
>フィボナッチ数列の一般項は次の式で表される:
f:id:neguse_atama:20210930015610p:plain
>この式は1843年にビネ (Jacques Philippe Marie Binet) が発表したことからビネの公式と呼ばれるが、それ以前の1730年(ド・モアブル)・1765年(オイラー)にも発表されており、ビネは最初の発見者ではない。
こうゆうの、歴史の暗記だったら、めっちゃ困るような...
いや、でも試験に出題される解答を正解として憶えるわけだから、けっきょくは変わらないはずです。
それで「諸説あり」ってことになるのかなー、モヤるけれど。
とにかく進めます。

さらに、性質について...
>フィボナッチ数列の隣接2項の商は黄金数 φ に収束する。
f:id:neguse_atama:20210930020001p:plain
>この性質は初期値 (F0 = 0, F1 = 1) に依らない。
>フィボナッチ数は完全数にはならない。より一般に、フィボナッチ数は倍積完全数にもならず、2つのフィボナッチ数の商も完全数にはならない。
>フィボナッチ数列の逆数和は収束し、記号 ψ で表される。
f:id:neguse_atama:20210930020458p:plain
>この ψ が無理数であることは証明されているが、超越数であるかどうかは分かっていない。
>任意の正の整数は、1つ以上の連続しない相異なるフィボナッチ数の和として一意に表すことができる(ゼッケンドルフの定理)。

そして、AIZU ONLINE JUDGEのALDS1_10_Aから、"Fibonacci Number"の出題では...
フィボナッチ数列の第 n 項の値を出力するプログラムを作成してください。
ここではフィボナッチ数列を以下の再帰的な式で定義します:
f:id:neguse_atama:20210930020757p:plain
ってことで、さっそく実装!

僕が作成、提出したコードは、以下のとおりです。

Aizu Online Judge in C++ #ALDS1_10_A : Fibonacci Number
/*
Aizu Online Judge in C++ #ALDS1_10_A : Fibonacci Number
https://onlinejudge.u-aizu.ac.jp/problems/ALDS1_10_A
 提出コードの解答例
 https://neguse-atama.hatenablog.com
*/
#include<bits/stdc++.h>
using namespace std;
int main(void){
    int n;
    cin>>n;
    vector<long long> fib;
    fib.push_back(1);
    fib.push_back(1);
    for(int i=2;i<=n;i++){
        fib.push_back(fib[i-2]+fib[i-1]);
    }
    cout<<fib[n]<<endl;
    return 0;
}

それから、類似の数列について...
>フィボナッチ数列の定義である初期値や漸化式をやや変更して、類似の数列が作れる。
>これらフィボナッチ数列の類似物を、項数 k に対応するラテン語またはギリシャ語に由来する倍数接頭辞を「フィボナッチ」と組み合わせた名称で呼ぶ。
・直前の三項の和として各項が定まる、トリボナッチ数列
・直前の四項の和に変更した、テトラナッチ数列
などなど...
で、フィボナッチ数列の最初の2項を 2, 1 に置き換えた数列の項をリュカ数と言って、フィボナッチ数列やリュカ数の列を一般化したものがリュカ数列で、これらの研究が現代のフィボナッチ数の理論の基礎となったのだそうです。

オマケに、1202年に出版された『算盤の書』について...
>15章からなる『算盤の書』の中で、フィボナッチは「インドの方法」(modus Indorum)としてアラビア数字を紹介した。
>この中では0から9の数字と位取り記数法が使われている。
>この本の中では位取り記数法の利点を、格子乗算とエジプト式除算を使い、簿記、単位の変換、利子の計算などへの応用を例にとって説明している。
>この本はヨーロッパの知識層へ広く受け入れられ、ヨーロッパ人の考え方そのものに大きな影響を及ぼした。
この本の中の「ウサギの出生率に関する数学的解法」とその回答で使用された数列が、後にフィボナッチ数列として知られるようになったみたいです。
・1つがいの兎は、産まれて2か月後から毎月1つがいずつの兎を産む。
・兎が死ぬことはない。
・この条件の下で、産まれたばかりの1つがいの兎は1年の間に何つがいの兎になるか?
すると月ごとのつがいの数は、直前の2項の和になるから、そこにフィボナッチ数が現れることになります。
よって問題の答えは、12カ月後の第13項、すなわち233(つがい)です。

ちなみに和算では「ねずみ算」と言う類題があって、そっちは等比数列になっています。
https://ja.wikipedia.org/wiki/ねずみ算
>正月に、ネズミのつがいがあらわれ、子を12匹産む。
>そして親と合わせて14匹になる。
>このネズミは、二月に子ネズミがまた子を12匹ずつ産むため、親と合わせて98匹になる。
>この様に、月に一度ずつ、親も子も孫もひ孫も月々に12匹ずつ産む時、12ヶ月でどれくらいになるかというと、276億8257万4402匹となる。

あと、古代エジプト(紀元前1650年前後)の数学書「リンド数学パピルス」にも類題があって...
ja.wikipedia.org
>エジプトの『アーメス・パピルス』には次の様な計算が載っている。
家 - 7
ネコ - 49
ネズミ - 343
小麦 - 2401
マス - 16807
これは「7つの家に7匹ずつのネコがいる。1匹のネコが7匹ずつのネズミをとる。1匹のネズミは7本の小麦をたべる。1本の小麦からはマス7杯分小麦がとれる。小麦はどれだけになるか」という意味なのだそうです。

設問の出典は、プログラミング問題のオンライン採点システム「Aizu Online Judge(AOJ)」です。
http://judge.u-aizu.ac.jp/onlinejudge/