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

C++で桁の階乗の積が等しくなる最大の数を求める方法

この記事では、与えられた数 N の各桁の階乗の積と等しくなるような、先頭や末尾に 0 や 1 を含まない最大の数を求める方法を解説します。

まず、具体例を使って問題を理解しましょう。

入力 − N = 4912

出力 − 73332222

説明 − 4! × 9! × 1! × 2! = 7! × 3! × 3! × 3! × 2! × 2! × 2! × 2! = 17,418,240

入力 − N = 340

出力 − 3322

なぜ素数の階乗に分解するのか

0! と 1! はどちらも 1 に等しいため、0 と 1 の桁は積に影響を与えません。一方、4!、6!、8!、9! はそれぞれ以下のように、素数の階乗の積で表すことができます。

  • 4! = 3! × 2! × 2!
  • 6! = 5! × 3!
  • 8! = 7! × 2! × 2! × 2!
  • 9! = 7! × 3! × 3! × 2!

つまり、答えとなる数は 2、3、5、7 のみで構成されます。桁数が多いほど数は大きくなるため、分解できる桁はすべて素数の階乗の積に置き換えることで、条件を満たす最大の数が得られます。なお、与えられた数が 0 と 1 のみで構成されている場合は、答えを求めることができません。

プログラムで使用するアプローチ

  • MaxNum() 関数内で、桁の総数を格納する int 型の変数 total_digits を作成し、さらに各数字の出現回数を格納する int 型の配列 Frq[] = {0} を初期化します。

  • i = 0 から i < total_digits までループし、各桁が素数(2、3、5、7)であるかどうかを判定します。

  • 現在の桁が素数であれば、配列 Frq[] の該当する位置に 1 を加算します。

  • 桁が素数でない場合は、個別の if 文で 4、6、8、9 のいずれかに該当するかを確認し、その桁を素数の階乗の積に分解して、対応する頻度を加算します。

  • 最終的な答えを格納するための空の文字列 ans を作成します。

  • 最終ステップに進む前に、元の数が 1 と 0 のみで構成されているかどうかを確認します。その場合は元の文字列をそのまま返し、そうでなければ次のステップへ進みます。

  • i = 9 から i >= 2 までループします。int 型の変数 C = Frq[i] を初期化し、for ループ内で while (C--) という条件の while ループを作成し、その中で ans += (char)(i + 48) を実行することで、大きい桁から順に答えを文字列 ans に格納していきます。

サンプルコード

#include <bits/stdc++.h>
using namespace std;
string MaxNum(string str){
    int total_digits = str.length();
    int Frq[15] = { 0 };
    //各数字の出現回数を取得
    for (int i = 0; i < total_digits; i++){
        if (str[i] == '1'|| str[i] == '2'|| str[i] == '3'|| str[i] == '5'|| str[i] == '7'){
            Frq[str[i] - 48] += 1;
        }
        // 4! = 2! * 2! * 3!
        if (str[i] == '4'){
            Frq[2] += 2;
            Frq[3]++;
        }
        // 6! = 5! * 3!
        if (str[i] == '6'){
            Frq[5]++;
            Frq[3]++;
        }
        // 8! = 7! * 2! * 2! * 2!
        if (str[i] == '8'){
            Frq[7]++;
            Frq[2] += 3;
        }
        // 9! = 7! * 3! * 3! * 2!
        if (str[i] == '9'){
            Frq[7]++;
            Frq[3] += 2;
            Frq[2]++;
        }
    }
    string ans = "";
    //数が1と0のみで構成されている場合
    if (Frq[1] == total_digits || Frq[0] == total_digits || (Frq[0] + Frq[1]) == total_digits){
        return str;
    }
    else{
        //条件を満たす最大の数を生成
        for (int i = 9; i >= 2; i--){
            int C = Frq[i];
            while (C--){
                ans += (char)(i + 48);
            }
        }
        return ans;
    }
}
//メイン関数
int main(){
    string str = "340";
    cout << MaxNum(str);
    return 0;
}

出力

上記のコードを実行すると、以下の出力が得られます。

3322
  1. C++で配列から4つの要素を選んだ最大積を求める方法

    n個の整数が格納された配列が与えられたとき、その中から4つの要素を選んで作れる積(クアドラプル)の最大値を求める問題について解説します。例えば、配列が [3, 5, 20, 6, 10] の場合、最大積は 6000 となり、このとき選ばれる4つの要素は 10, 5, 6, 20 です。解法のアプローチこの問題は、配列をソートすることで効率的に解くことができます。最大積の候補として考えられるのは以下の3パターンだけです。配列を昇順にソートするx = 最後の4要素(最も大きい4つ)の積とするy = 最初の4要素(最も小さい4つ)の積とするz = 最初の2要素と最後の2要素の積とするx、y、z のう

  2. C++で積がPとなるN個の整数の最大GCDを求める方法

    2つの整数 N と P が与えられているとします。P は N 個の未知の整数の積であり、そのときそれらの整数の最大公約数(GCD)としてあり得る最大値を求めるのが課題です。 例として、N = 3、P = 24 の場合を考えてみましょう。3つの整数の組み合わせとしては {1, 1, 24}、{1, 2, 12}、{1, 3, 8}、{1, 4, 6}、{2, 2, 6}、{2, 3, 4} などが考えられます。それぞれのGCDは 1, 1, 1, 1, 2, 1 となるため、この場合の答えは 2 です。 解法のアプローチ まず P のすべての素因数を求め、ハッシュマップに格納します。各素因数が