C++における再帰関数の実装例

コラッツ予想(角谷予想)

自然数に対して、偶数なら2で割り、奇数なら3倍して1を足す操作を繰り返すと、最終的に1に到達するという予想。再帰関数で操作回数をカウントする。

#include <iostream>
using namespace std;

int countSteps(int num) {
    if (num == 1) return 0;
    if (num % 2 == 0) return 1 + countSteps(num / 2);
    return 1 + countSteps(num * 3 + 1);
}

int main() {
    int input;
    cin >> input;
    cout << countSteps(input) << endl;
    return 0;
}

最大公約数(ユークリッドの互除法)

二つの整数の最大公約数を再帰的に求める手法。

#include <iostream>
using namespace std;

int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

int main() {
    int x, y;
    cin >> x >> y;
    cout << gcd(x, y) << endl;
    return 0;
}

数のカウント

自然数nに対して、n/2以下の各数について再帰的にカウントを行う問題。

#include <iostream>
using namespace std;

int totalCount = 0;

void countNumbers(int limit) {
    for (int i = 1; i <= limit / 2; i++) {
        totalCount++;
        countNumbers(i);
    }
}

int main() {
    int n;
    cin >> n;
    totalCount = 1; // 元の数自身
    countNumbers(n);
    cout << totalCount << endl;
    return 0;
}

リンゴの配置問題

m個のリンゴをn個の皿に配置する方法の数を求める。空の皿を許容する場合の分割問題。

#include <iostream>
using namespace std;

int countWays(int apples, int plates) {
    if (apples == 0 || plates == 1) return 1;
    if (plates > apples) return countWays(apples, apples);
    return countWays(apples, plates - 1) + countWays(apples - plates, plates);
}

int main() {
    int m, n;
    cin >> m >> n;
    cout << countWays(m, n) << endl;
    return 0;
}

数字根(ディジタルルート)

整数の各桁の和を求め、一桁になるまで繰り返す処理。

#include <iostream>
using namespace std;

int digitSum(int num) {
    int sum = 0;
    while (num > 0) {
        sum += num % 10;
        num /= 10;
    }
    return sum;
}

void findDigitalRoot(int num) {
    if (num < 10) {
        cout << num << endl;
        return;
    }
    findDigitalRoot(digitSum(num));
}

int main() {
    int n;
    cin >> n;
    findDigitalRoot(n);
    return 0;
}

アッカーマン関数

再帰的に定義される二変数関数で、計算量が非常に急激に増大する特性を持つ。

#include <iostream>
using namespace std;

int ackermann(int m, int n) {
    if (m == 0) return n + 1;
    if (n == 0) return ackermann(m - 1, 1);
    return ackermann(m - 1, ackermann(m, n - 1));
}

int main() {
    int a, b;
    cin >> a >> b;
    cout << ackermann(a, b) << endl;
    return 0;
}

最小公倍数

二つの整数の最小公倍数を再帰的に探索する。

#include <iostream>
using namespace std;

int findLCM(int a, int b, int multiple) {
    if (multiple % a == 0 && multiple % b == 0) return multiple;
    return findLCM(a, b, multiple + 1);
}

int main() {
    int x, y;
    cin >> x >> y;
    int start = (x > y) ? x : y;
    cout << findLCM(x, y, start) << endl;
    return 0;
}

因数分解のパターン数

整数nを因数の積として表す方法の数を再帰的に求める。

#include <iostream>
using namespace std;

int countFactorizations(int num, int minFactor) {
    if (num == 1) return 1;
    int count = 0;
    for (int i = minFactor; i <= num; i++) {
        if (num % i == 0) {
            count += countFactorizations(num / i, i);
        }
    }
    return count;
}

int main() {
    int n;
    cin >> n;
    cout << countFactorizations(n, 2) << endl;
    return 0;
}

エルミート多項式

エルミート多項式は再帰関係を用いて定義される直交多項式の一種。

#include <iostream>
using namespace std;

int hermite(int n, int x) {
    if (n == 0) return 1;
    if (n == 1) return 2 * x;
    return 2 * x * hermite(n - 1, x) - 2 * (n - 1) * hermite(n - 2, x);
}

int main() {
    int degree, value;
    cin >> degree >> value;
    cout << hermite(degree, value) << endl;
    return 0;
}

タグ: C++ 再帰関数 アルゴリズム データ構造

6月12日 20:24 投稿