Pythonで指定したnに対する数列Sの最後の桁を求めるプログラム
ある値 n が与えられたとき、次の式で定義される数列 S の最後の桁(一の位)を求めることを考えます。
$$\sum_{i=0\: 2^{^{i}}\leqslant n}^{\alpha } \sum_{j=0}^{n} 2^{2^{^{i}+2j}}$$
例えば、入力が n = 2 の場合、出力は 6 になります。条件 2^i ≤ n を満たすのは i = 0 と i = 1 のみなので、計算は次のようになります。
- S0 = 2^(2^0 + 0) + 2^(2^0 + 2) + 2^(2^0 + 4) = 42
- S1 = 2^(2^1 + 0) + 2^(2^1 + 2) + 2^(2^1 + 4) = 84
合計は 42 + 84 = 126 となるため、答えは最後の桁の 6 です。
解法のアプローチ
巨大な冪乗をそのまま計算すると処理時間やメモリの面で不利になるため、ここでは「一の位だけを追跡する」という工夫を使います。手順は以下の通りです。
- total を 0、temp を 1 で初期化します。
- temp が n 以下である間、次の処理を繰り返します。
- total に
2^temp mod 10(2 の temp 乗の一の位)を加算します。 - temp を 2 倍します(temp は 1, 2, 4, 8, … と変化し、式の中の 2^i に対応します)。
- total に
- ループ終了後、n が奇数なら total に 5 を掛け(1 + 4)、偶数ならそのままにして、10 で割った余りを求めます。
- total を返します。
なぜこのアルゴリズムで正しく求まるのか
各 i について、内側の和は次のように変形できます。
2^(2^i) × (4^0 + 4^1 + … + 4^n)
ここで 4^k の一の位は「1, 4, 6, 4, 6, …」と循環するため、次のことが言えます。
- n が偶数の場合: 括弧内の和の一の位は 1 になり、内側の和の一の位は 2^(2^i) の一の位と一致します。
- n が奇数の場合: 括弧内の和の一の位は 5 になり、内側の和の一の位は 2^(2^i) × 5 の一の位になります。
したがって、「temp = 1, 2, 4, … に対する 2^temp の一の位の総和」を求め、n の偶奇に応じて 1 倍または 5 倍すれば、数列全体の一の位が得られます。計算量は O(log n) と非常に効率的です。
Pythonでの実装例
理解を深めるために、以下の実装を見てみましょう。
def solve(n):
total = 0
temp = 1
while (temp <= n):
total += pow(2, temp, 10)
temp *= 2
total = total * (1 + (4 if n % 2 == 1 else 0)) % 10
return total
n = 2
print(solve(n))
pow(2, temp, 10) は「2 の temp 乗を 10 で割った余り」を高速に計算できる Python の組み込み関数です。巨大な冪乗を実際に展開しないため、n が大きくなっても瞬時に答えを得られます。
入力
2
出力
6
まとめ
本記事では、二重シグマで定義される数列 S の最後の桁を Python で求める方法を紹介しました。冪乗の一の位が循環する性質と、n の偶奇による補正(奇数なら 5 倍)を組み合わせることで、O(log n) の計算量で効率よく答えを導けるのがポイントです。
-
Pythonで配列(リスト)の合計を求める方法をわかりやすく解説
この記事では、配列(リスト)の合計値を求めるという問題に対して、Pythonでの解決策とアプローチをわかりやすく解説します。 問題の定義 配列が入力として与えられたとき、その配列に含まれるすべての要素の合計を計算することを目標とします。 例えば、[1, 2, 3, 4, 5] という配列が与えられた場合、出力は 15 になります。 アプローチ1:ループを使った素朴な方法(総当たり法) 最も基本的な方法は、リストを先頭から順に走査し、各要素を合計用の変数に加算していくやり方です。手順は以下の通りです。 合計を格納する変数を 0 で初期化します。 for ループでリストの各要素を取り出し、順番に
-
Pythonで円柱の周囲長を求めるプログラムの書き方
この記事では、以下の問題をPythonを使って解く方法を解説します。 問題の定義 問題: 直径と高さを入力として受け取り、円柱の周囲長を求める。 ここでいう「周囲長」とは、円柱を横から見たときに現れる長方形の外周のことです。つまり、円柱の側面を展開すると長方形になり、その縦が円柱の高さ、横が円の直径(円周ではありません)に相当します。 したがって、周囲長は次の式で表せます。 周囲長 = 2 × ( 高さ h + 直径 d ) d:円柱の直径 h:円柱の高さ 実装例 それでは、実際のコードを見てみましょう。 # 円柱の周囲長を計算する関数 def perimeter(diameter, he