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

Pythonで数値をn回連結した際の剰余(モジュラス)を効率的に求めるプログラム

ある数値 A が与えられたとします。このAを n回連結 して大きな数Xを生成し、そのXを m で割った余り(モジュラス)を求めるのが今回の課題です。

例えば、入力が A = 15n = 3m = 8 の場合を考えてみましょう。このとき生成される数値Xは「151515」となり、151515 mod 8 = 3 であるため、出力は 3 になります。

解法のアプローチ

連結後の数値は桁数が膨大になる可能性があるため、実際に文字列として連結してから計算するのは非効率です。そこで、数学的な性質を利用して直接剰余を計算します。手順は以下の通りです。

  • Aが0の場合は、0を返す
  • an := A
  • c := Aの桁数
  • c := 10^c(桁数に対応する10の冪乗)
  • d := c − 1
  • newmod := d × m
  • val := (c ^ n mod newmod) − 1
  • val := (val + newmod) mod newmod
  • an := (an × val) mod newmod
  • (an ÷ d) の切り捨て値を返す

なぜこの方法で求まるのか

Aをn回連結した数値Xは、等比数列の和として次のように表せます。

X = A × (c^n − 1) ÷ d ※ここで c = 10^桁数、d = c − 1

割り算を含む式はモジュロ演算と相性が悪いため、あらかじめ d × m を法として計算しておくことで、最後にdで割り切れる形に整えられます。これにより、巨大な連結数を実際に構築することなく、O(log n) の計算量で答えを導き出せるのです。

実装例

以下のPythonコードを見て、理解を深めましょう。

def solve(A, n, m):
   if A == 0:
      return 0
   an = A
   c = len(str(A))
   c = 10**c
   d = c - 1
   newmod = d * m
   val = pow(c, n, newmod) - 1
   val = (val + newmod) % newmod
   an = (an * val) % newmod
   return an // d

A = 15
n = 3
m = 8
print(solve(A, n, m))

ここではPythonの組み込み関数 pow(c, n, newmod) を使用しています。これは「cのn乗をnewmodで割った余り」を高速に計算してくれる便利な関数です。

入力

15, 3, 8

出力

3

このように、数値を実際に連結せずとも冪乗のモジュロ演算を活用すれば、非常に大きな連結数の剰余も瞬時に求めることができます。

  1. Pythonでリスト内の最小値を見つける方法を解説

    この記事では、リストの中から最小の数値を見つける方法について、具体的なサンプルコードとともに詳しく解説します。問題の概要問題: 数値のリストが与えられたとき、その中に含まれる最も小さい数値を画面に表示すること。この問題を解くアプローチは主に2つあります。ひとつは sort() メソッドを使ってリストを昇順に並べ替え、先頭の要素(インデックス0)を取得する方法。もうひとつは、Pythonに標準で用意されている組み込み関数 min() を使う方法です。それぞれ順番に見ていきましょう。方法1:sort()メソッドで並べ替えて最小値を取得するまずはリストを昇順にソートし、先頭の要素を取り出す方法です。

  2. Pythonプログラムで数の偶数の約数の合計を求める方法

    この記事では、以下の問題文に対する解決策について詳しく解説します。 問題文:ある数が与えられたとき、その数のすべての偶数の約数(因子)の合計を求めて表示します。 アプローチ まず、与えられた数が奇数であるかどうかを確認します。奇数には偶数の約数が存在しないため、その場合は 0 を返します。 数が偶数である場合は、実際の計算に進みます。ここでのポイントは、20(つまり1)以外のすべての項を掛け合わせることで、偶数の約数の合計が得られるという点です。 偶数の約数からすべての奇数を取り除くために、20 に相当する「1」を無視します。この処理を行うことで、残るのは偶数の約数のみとなります。なお、2 は