Pythonで約数の約数の個数の総和を求めるプログラム
問題の概要
2つの整数 m と a が与えられたとします。このとき、次のように定義される数 n を考えます。
n = p1(a+1) × p2(a+2) × … × pm(a+m)
ここで、pi は i 番目の素数(i > 0)を表します。求めたいのは、n のすべての約数 x に対する f(x) の値の合計 k です。f(x) は「x の約数の個数」を返す関数です。
具体例で確認する
入力が m = 2、a = 1 の場合を考えてみましょう。このときの出力は 60 になります。
- n = 22 × 33
- n = 4 × 27
- n = 108
108 の約数は、1, 2, 3, 4, 6, 9, 12, 18, 27, 36, 54, 108 の12個です。
各約数に対する f(x) の値をすべて足し合わせると、次のようになります。
f(1) + f(2) + f(3) + f(4) + f(6) + f(9) + f(12) + f(18) + f(27) + f(36) + f(54) + f(108)
= 1 + 2 + 2 + 4 + 4 + 3 + 5 + 6 + 4 + 9 + 8 + 12
= 60
解法の考え方
n = ∏ piei と素因数分解できるとき、n の各約数 d についてその約数の個数 τ(d) を合計した値は、素因数ごとに独立して計算できます。具体的には、指数 e に対して 1 + 2 + … + (e+1) = (e+1)(e+2)/2 を各素因数について掛け合わせたものが答えになります。
本問題では指数が ei = a + i となるため、答えは次の式で表せます。
k = ∏i=1..m (a+i+1)(a+i+2)/2
この積を効率よく求めるため、あらかじめ summ(n) = n(n+1)/2 の累積積リストを作成し、大きな数の除算はモジュロ逆数を利用して処理します。
アルゴリズムの手順
- MOD := 109 + 7 とする。
- 関数 summ(n) を定義する:((n × (n + 1)) / 2) の床関数値を返す。
- 関数 division(a, b, mod) を定義する:a ÷ b の結果を mod で割った余りを返す。
- a mod b = 0 の場合は、a / b の床関数値をそのまま返す。
- それ以外の場合は、a := a + mod × division((-a) mod b, mod mod b, b) としてから、(a / b) mod mod を返す。
- mat := [1] というリストを用意する。
- mat の長さが m + a 以下である間、mat の末尾に (mat[-1] × summ(len(mat)+1)) mod MOD を追加していく。
- division(mat[m + a], mat[a], MOD) を返す。
Pythonでの実装例
それでは、実際のコードを見てみましょう。
MOD = 10**9 + 7
def summ(n):
return ((n) * (n + 1)) // 2
def division(a, b, mod):
if a % b == 0:
return a // b
a += mod * division((-a) % b, mod % b, b)
return (a // b) % mod
def solve(m, a):
mat = [1]
while len(mat) <= m + a:
mat.append((mat[-1] * summ(len(mat)+1)) % MOD)
return division(mat[m + a] , mat[a], MOD)
print(solve(2, 1))実行結果
入力:
2, 1
出力:
60
まとめ
この記事では、n = p1(a+1) × … × pm(a+m) で表される数 n の各約数について、さらにその約数の個数を合計する問題を扱いました。答えは各素因数の指数から (e+1)(e+2)/2 を掛け合わせる形で閉形式で求められるため、累積積とモジュロ逆数を組み合わせれば、大きな m や a に対しても高速に計算できます。競技プログラミングで頻出の「約数個数関数の和」と「mod 下的除算」のテクニックを同時に学べる良い例題といえるでしょう。
-
Pythonプログラムで数の偶数の約数の合計を求める方法
この記事では、以下の問題文に対する解決策について詳しく解説します。 問題文:ある数が与えられたとき、その数のすべての偶数の約数(因子)の合計を求めて表示します。 アプローチ まず、与えられた数が奇数であるかどうかを確認します。奇数には偶数の約数が存在しないため、その場合は 0 を返します。 数が偶数である場合は、実際の計算に進みます。ここでのポイントは、20(つまり1)以外のすべての項を掛け合わせることで、偶数の約数の合計が得られるという点です。 偶数の約数からすべての奇数を取り除くために、20 に相当する「1」を無視します。この処理を行うことで、残るのは偶数の約数のみとなります。なお、2 は
-
Pythonで配列(リスト)の合計を求める方法をわかりやすく解説
この記事では、配列(リスト)の合計値を求めるという問題に対して、Pythonでの解決策とアプローチをわかりやすく解説します。 問題の定義 配列が入力として与えられたとき、その配列に含まれるすべての要素の合計を計算することを目標とします。 例えば、[1, 2, 3, 4, 5] という配列が与えられた場合、出力は 15 になります。 アプローチ1:ループを使った素朴な方法(総当たり法) 最も基本的な方法は、リストを先頭から順に走査し、各要素を合計用の変数に加算していくやり方です。手順は以下の通りです。 合計を格納する変数を 0 で初期化します。 for ループでリストの各要素を取り出し、順番に