C++
 Computer >> コンピューター >  >> プログラミング >> C++

【C++】指定されたインデックスのN個のフィボナッチ数のGCDを効率的に求める方法

本記事では、指定された複数のインデックスに対応するN個のフィボナッチ数の最大公約数(GCD)を、C++で効率的に求める方法を解説します。

フィボナッチ数列と問題の概要

まずおさらいとして、フィボナッチ数列は「0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …」のように、直前の2つの項の和によって定義される数列です。インデックスは0から始まるため、0番目の要素は0、1番目の要素は1となります。

例えば、インデックス{2, 3, 4, 5}に対応するフィボナッチ数は{1, 2, 3, 5}であり、これらのGCDは1です。

鍵となる性質:GCD(Fibo(i), Fibo(j)) = Fibo(GCD(i, j))

この問題を解くうえで非常に強力なのが、フィボナッチ数列が持つ次の美しい数学的性質です。

GCD(Fibo(i), Fibo(j)) = Fibo(GCD(i, j))

つまり、「i番目のフィボナッチ数とj番目のフィボナッチ数のGCD」は、「iとjのGCDをインデックスとするフィボナッチ数」と等しくなります。この性質を利用すれば、巨大なフィボナッチ数同士のGCDを直接計算する必要はありません。まずインデックス同士のGCDを求め、その値に対応するフィボナッチ数を1つだけ計算すればよいため、計算量を大幅に抑えられます。

C++による実装例

#include <iostream>
#include <algorithm>
using namespace std;
int getFiboTerm(int n){
    int fibo[n + 2];
    fibo[0] = 0; fibo[1] = 1;
    for(int i = 2; i<= n; i++){
        fibo[i] = fibo[i - 1] + fibo[i - 2];
    }
    return fibo[n];
}
int getNFiboGCD(int arr[], int n){
    int gcd = 0;
    for(int i = 0; i < n; i++){
        gcd = __gcd(gcd, arr[i]);
    }
    return getFiboTerm(gcd);
}
int main() {
    int indices[] = {3, 6, 9};
    int n = sizeof(indices)/sizeof(indices[0]);
    cout << "GCD of fibo terms using indices: " <<
    getNFiboGCD(indices, n);
}

コードの解説

  • getFiboTerm関数:動的計画法を用いて、n番目のフィボナッチ数を計算して返します。
  • getNFiboGCD関数:配列内のすべてのインデックスに対して__gcd関数でGCDを順に求め、最終的に得られたGCDに対応するフィボナッチ数を返します。
  • main関数:インデックスの配列{3, 6, 9}を渡し、結果を出力します。

実行結果

GCD of fibo terms using indices: 2

結果の検証

インデックス{3, 6, 9}の場合、まずGCD(3, 6, 9) = 3を求めます。次に、3番目のフィボナッチ数Fibo(3) = 2を計算します。実際に各フィボナッチ数を確認すると、Fibo(3) = 2、Fibo(6) = 8、Fibo(9) = 34であり、GCD(2, 8, 34) = 2となるため、上記の性質どおりの正しい結果が得られていることがわかります。

  1. C++で配列要素の階乗の最大公約数(GCD)を求める方法

    N個の要素を持つ配列Aが与えられたとき、配列内のすべての要素の階乗の最大公約数(GCD)を求めることを考えます。例えば、配列の要素が {3, 4, 8, 6} の場合、各要素の階乗は 3! = 6、4! = 24、8! = 40320、6! = 720 となり、これらのGCDは 6 になります。解法のポイントここで重要な数学的な性質があります。2つの数のGCDとは、両方の数を割り切る最大の数のことです。階乗の場合、小さい数の階乗は必ず大きい数の階乗を割り切ることができます。つまり、2つの階乗のGCDは、小さい方の数の階乗そのものになります。例えば、3! と 5! のGCDを考えると、3! =

  2. C++でn個の数のGCD(最大公約数)とLCM(最小公倍数)を求めるプログラム

    本記事では、複数の整数からGCD(最大公約数)とLCM(最小公倍数)を求めるC++プログラムを解説します。GCD(Greatest Common Divisor:最大公約数)とは、2つ以上の整数(すべてがゼロではないもの)に共通する約数の中で最大となる正の整数のことです。英語では Greatest Common Factor(最大公因子)とも呼ばれます。一方、LCM(Least Common Multiple:最小公倍数)とは、2つの数のどちらの倍数にもなる数のうち、ゼロ以外で最小の数を指します。アルゴリズムまず、処理の流れを擬似コードで確認しましょう。GCDの計算には、剰余を繰り返し求める「