リリース・改善中
Algorithm
最大公約数と最小公倍数、剰余演算と逆元、繰り返し二乗法、エラトステネスの篩、nCr mod p まで、アルゴリズムで使う整数論の道具をまとめます。
整数論は整数、とくに割り算と余りの性質を扱う数学の分野です。アルゴリズムでは、ユークリッドの互除法で最大公約数と最小公倍数を求め、剰余演算で巨大な数を余りとして扱い、拡張ユークリッドの互除法やフェルマーの小定理でモジュラ逆元を求めます。さらに繰り返し二乗法、エラトステネスの篩、素因数分解、素数を法とする二項係数の計算が加わって、ひとつの道具箱になります。
これらの道具は、コーディング面接や競技プログラミングで「答えを 10^9 + 7 で割った余りを出力せよ」という形で頻繁に登場します。実務では RSA や Diffie-Hellman などの公開鍵暗号、ハッシュ関数、乱数生成器、チェックディジットの土台になっています。ほとんどが対数時間かほぼ線形時間で動くため、仕組みを知っていれば素朴な方法では終わらない計算を一瞬で処理できます。
まず剰余演算の性質とユークリッドの互除法を手で追い、次に繰り返し二乗法と篩を自分で実装してみましょう。その後モジュラ逆元と nCr mod p に進み、C++ や Java を使うなら乗算のオーバーフローと負の余りの扱いを必ず練習してください。Python の pow(a, e, m) や math.gcd といった標準機能もあわせて覚えておくと便利です。
gcd(a, b) = gcd(b, a mod b) を繰り返して最大公約数を O(log n) で求めます。拡張版は ax + by = gcd(a, b) を満たす係数も同時に求めます。
加算・減算・乗算は余りを保つので、各ステップで余りを取って数を小さく保ちます。割り算はモジュラ逆元を掛ける操作に置き換えます。
指数を二進数として見て底を二乗しながら掛けることで、a^e mod m を e 回ではなく約 log e 回の乗算で計算します。
各素数の倍数を i × i から消していき、n 以下の素数をすべて O(n log log n) で求めます。最小素因数の表があれば素因数分解も高速です。
gcd はユークリッドの互除法で最大公約数を求め、最小公倍数は a // gcd(a, b) * b で得られます。mod_pow は指数のビットを一つずつ見ながら二乗と乗算を繰り返す繰り返し二乗法で、素数 p を法とするとき a^(p-2) は a のモジュラ逆元になります。sieve はエラトステネスの篩で 30 以下の素数をすべて求めます。ファイルに保存して python number_theory.py で実行してください。
number_theory.py
import math
def gcd(a: int, b: int) -> int:
while b:
a, b = b, a % b
return a
def mod_pow(base: int, exp: int, mod: int) -> int:
result, base = 1 % mod, base % mod
while exp > 0:
if exp & 1:
result = result * base % mod
base = base * base % mod
exp >>= 1
return result
def sieve(n: int) -> list[int]:
is_prime = [False, False] + [True] * (n - 1)
for i in range(2, math.isqrt(n) + 1):
if is_prime[i]:
for j in range(i * i, n + 1, i):
is_prime[j] = False
return [i for i, p in enumerate(is_prime) if p]
MOD = 10**9 + 7
print(gcd(84, 36), 84 // gcd(84, 36) * 36) # 12 252
print(mod_pow(3, 200, 13)) # 9
print(mod_pow(3, MOD - 2, MOD)) # 333333336, the inverse of 3
print(sieve(30)) # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
python number_theory.pyインストールから 数学と整数論 の中心となる考え方まで、6 章で順を追って学びます。
数学と整数論 について質問し、経験を共有し、意見を交わす場所です。
まだディスカッションはありません。最初の話題を始めましょう。
コメント 0件
ログイン · ログインするとコメントできます。
最初のコメントを書いてみましょう。