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

Pythonで数の因子の最小合計を求めるプログラム|素因数分解の考え方

本記事では、与えられた整数について、積が元の数と等しくなる因子の組み合わせの中から合計が最小となる値を求める方法を、Pythonのコード例とともに解説します。

問題定義

入力として1つの整数が与えられます。この数を複数の因子の積として表したとき、因子の合計が最小になるケースを求めてください。

すべての因子の組み合わせを網羅的に調べて合計を比較する方法もありますが、実はもっとシンプルで効率的なアプローチが存在します。

考え方:素因数の合計が最小になる

鍵となるのは次の性質です。積が一定の値になるとき、因子の合計が最小になるのは、すべての因子を素数まで分解した場合(素因数分解した場合)です。

これは、2以上の合成数を a × b(a ≥ 2、b ≥ 2)に分解すると、a + b ≤ a × b が常に成り立つためです。つまり、合成数の因子をさらに分解しても積は変わらず、合計は減るか最大でも変わりません。したがって、それ以上分割できない素因数の状態が最適解となります。

例として 12 を考えてみましょう。12 = 6 × 2 のとき合計は 8、12 = 3 × 4 のとき合計は 7、そして 12 = 2 × 2 × 3 と素因数分解したときの合計は 2 + 2 + 3 = 7 となり、これが最小値です。

反復処理による実装例

以下は、試し割り法によって素因数分解を行い、素因数の合計を求めるPythonコードです。

# 反復アプローチによる実装
def findMinSum(num):
    sum_ = 0
    # 2から順に割れるだけ割り、素因数を合計に加算する
    i = 2
    while(i * i <= num):
        while(num % i == 0):
            sum_ += i
            num //= i   # 整数除算で割る
        i += 1
    # ループ終了後に残った数は、それ自体が素因数
    sum_ += num
    return sum_

# 動作確認
num = 12
print(findMinSum(num))

出力

7

コードのポイント

  • √num まで試し割り: 外側のループ条件を i * i <= num とすることで、√num 以下の約数だけを調べればよく、計算量を O(√n) に抑えられます。
  • 同じ素因数をまとめて処理: 内側の while ループで、同じ素因数で割り切れる限り、加算と除算を繰り返します。
  • 残った数の処理: ループ終了時に 1 より大きい数が残っていれば、それは √num より大きい素因数なので、そのまま合計に加えます。
  • 整数除算を使用: Python 3 では / は浮動小数点除算になるため、// を使うことで正確な整数演算が行えます。

まとめ

本記事では、数の因子の最小合計を求める問題に対して、素因数分解を利用した効率的な解法を紹介しました。「積が固定なら、素因数の和が最小になる」という性質を理解すれば、全探索を行わずとも O(√n) の計算量で答えを得られます。ぜひご自身のコードにも応用してみてください。

  1. 【Python】ある数の最大の素因数を求めるプログラムの書き方

    この記事では、「与えられた整数の最大の素因数を求める」という問題に対する解決方法を、具体的なコード例とともにわかりやすく解説します。 問題文 正の整数 n が与えられたとき、その数の最大の素因数を求めます。 例えば n = 15 の場合、15 は 3 × 5 と素因数分解できるため、答えは 5 となります。 解き方のアプローチ 入力された数を、小さい約数から順番に割っていくことで素因数分解します。 割り切れるたびに、その時点での約数(素因数)を「最大値」として更新していきます。 平方根まで調べれば十分なため、計算量を抑えられます。 実装例(サンプルコード) import math def

  2. Pythonプログラム:数の一意な素因数の積を求める方法

    はじめに 本記事では、次の問題に対する解き方を学びます。 問題文: 整数 n が与えられたとき、その数が持つ一意な(重複しない)素因数をすべて求め、それらの積を返します。 例: 入力:num = 11 出力:積は 11 説明: 入力された数は 11 で、素因数は 11 のみです。 したがって、その積も 11 となります。 アプローチ1:総当たり法(ブルートフォース) i = 2 から n+1 までの for ループを使い、i が n の約数であるかどうかを確認します。約数であれば、さらに i 自身が素数かどうかを判定し、素数なら積に掛け合わせます。この処理を i が n に達するまで繰り返しま