M.Hiroi's Home Page

Memorandum

数学編

M.Hiroi の数学に関する覚え書です
[ Home | Math ]

初等整数論 [2]

●合同式

数学の世界では、2 つの整数 \(a, b\) を 2 以上の整数 \(n\) で割ったとき、その剰余が等しいことを「合同」といい、以下の式で表します。

\( a \equiv b \pmod n\)

これを「合同式」といい、"a 合同 b モッド n" または "n を法として a と b は合同" と読みます。

合同式の +, -, *, べき乗では、次の規則が成立します。

\(a \equiv b \pmod n, \ c \equiv d \pmod n\) のとき、\(a + c \equiv b + d\)
\(a \equiv b \pmod n, \ c \equiv d \pmod n\) のとき、\(a - c \equiv b - d\)
\(a \equiv b \pmod n, \ c \equiv d \pmod n\) のとき、\(a \times c \equiv b \times d\)
\(a \equiv b \pmod n\) のとき、\(a^k \equiv b^k\) (k は自然数)

ただし、合同式の除算には条件があります。

\(a \times b \equiv a \times c \pmod n\) で \(a\) と \(n\) が互いに素であるとき、\(b \equiv c \pmod n\) が成り立つ

「互いに素」とは、\(a, n\) の共通の約数が 1 しかないこと、つまり最大公約数 \(\gcd(a, n)\) の値が 1 であることと同じです。また、\(f(x\)) を整数係数多項式とすると、\(a \equiv b \pmod n\) のとき、\(f(a) \equiv f(b)\) が成立します。

Python の場合、剰余は演算子 % で求めることができます。簡単な例を示しましょう。

>>> 12345678 % 256
78
>>> 123456789 % 256
21
>>> 1234567890 % 256
210
>>> 12345678900 % 256
52
>>> a = 12345678
>>> b = a % 256
>>> b
78
>>> c = 123456789
>>> d = c % 256
>>> d
21
>>> (a + c) % 256
99
>>> (b + d) % 256
99
>>> (a - c) % 256
57
>>> (b - d) % 256
57
>>> (a * c) % 256
102
>>> (b * d) % 256
102
>>> (a ** 5) % 256
224
>>> (b ** 5) % 256
224

>>> 15240 % 256
136
>>> 34440 % 256
136

>>> 15240 % 3
0
>>> 34440 % 3
0
>>> (15240 // 3) % 256
216
>>> (34440 // 3) % 256
216

>>> 15240 % 4
0
>>> 34440 % 4
0
>>> (15240 // 4) % 256
226
>>> (34440 // 4) % 256
162

もう一つ、有名な定理を紹介します。

\(a\) と \(n\) が互いに素のとき、\(a, \ 2a, \ 3a, \ \cdots, \ (n - 2)a, \ (n - 1)a\) を \(n\) で割ったときの余りはすべて異なる

本当にそうなるか実際に試してみましょう。

>>> a = 10
>>> b = 7
>>> for n in range(1, b):
....     print(a * n % b)
....
3
6
2
5
1
4

証明は「背理法」を使うと簡単です。\(ia\) と \(ja\) (\(i \gt j\)) を \(n\) で割った余りが同じ値 \(x\) だと仮定しましょう。すると、次式が成立するはずです。

\(\begin{array}{llll} & ia & \equiv & x \pmod n \\ - & ja & \equiv & x \pmod n \\ \hline & (i-j)a & \equiv & 0 \pmod n \end{array}\)

\((i-j)a\) を \(n\) で割った余りは \(0\) になるので、\((i-j)a\) は \(n\) の倍数でなければいけません。\(i, j\) の前提条件 \(1 \leq i \lt n, \ 1 \leq j \lt n\) より、\(1 \leq i - j \lt n\) になるので、\(i - j\) は \(n\) で割り切れることはありません。そして、\(a\) と \(n\) は互いに素なので、\(a\) も \(n\) で割り切れることはありません。つまり、\((i-j)a\) は \(n\) の倍数ではないので、最初の仮定「\(ia\) と \(ja\) (\(i \gt j\)) を \(n\) で割った余りが同じ値 \(x\) になる」が矛盾していて、余りはすべて異なる値になることが導かれました。

●フェルマーの小定理

\(n\) が素数で \(a\) と \(n\) が互いに素のとき、\(a^{n - 1}\) を \(n\) で割ると余りが必ず 1 になります。これを「フェルマーの小定理」といい、合同式で書くと次のようになります。

\(a^{n-1} \equiv 1 \pmod n\)

本当にそうなるのか、実際に試してみましょう。

>>>> 10 ** (3 - 1) % 3
1
>>>> 100 ** (3 - 1) % 3
1
>>>> 100 ** (7 - 1) % 7
1
>>>> 1000 ** (7 - 1) % 7
1
>>>> 1000 ** (11 - 1) % 11
1
>>>> 10000 ** (11 - 1) % 11
1
>>>> 10000 ** (97 - 1) % 97
1

確かに余りが 1 になりますね。

フェルマーの小定理の証明 (一例) を示します。

  1. [定理] \(a\) と \(n\) が互いに素のとき、\(a, 2a, \ldots, (n - 1)a\) を \(n\) で割った余りはすべて異なる
  2. \(a, 2a, \ldots, (n - 1)a\) を乗算する
  3. \(a \times 2a \times \cdots \times (n - 1)a = (n - 1)! \times a^{n-1}\)
  4. 左辺式の剰余は各因子の剰余を乗算したものと同じになるので、1 の定理により \((n - 1)!\) になる
  5. \((n - 1)! \equiv (n - 1)! \times a^{n-1} \pmod n\)
  6. \(n\) と \((n - 1)!\) は互いに素なので、両辺を \((n - 1)!\) で割り算すると、フェルマーの小定理になる
  7. \(a^{n-1} \equiv 1 \pmod n\)

このほかにも、いろいろな証明方法があります。興味のある方は 参考 URL 2, 5 をお読みください。

●オイラーのトーシェント関数

数学の整数論では、整数 \(n\) に対して、\(n\) 以下の自然数で \(n\) と互いに素となる個数を求める関数を、「オイラーのトーシェント関数 (Euler's totient function)」といいます。慣例的に \(\varphi(n)\) と表記されることから、オイラーのファイ関数 (phi function) と呼ばれることもあります。

たとえば、1, 2, 3, 4 の中で 4 と互いに素となる数は 1 と 3 の 2 つあるので、totient(4) は 2 になります。totient(5) は、5 が素数なので、1, 2, 3, 4 と 5 は互いに素となるため、totient(5) は 4 になります。p を素数とすると、totient(p) = p - 1 になります。

幸いなことに、\(\varphi(n)\) を求める公式があるので、それを使うと高速に計算することができます。\(n\) の素因数分解が \({p_i}^a \times {p_j}^b \times \cdots \times {p_k}^c\) とすると、\(\varphi(n)\) は以下の式で求めることができます。

\( \varphi(n) = n \times (1 - \dfrac{1}{p_i}) \times (1 - \dfrac{1}{p_j}) \times \cdots \times (1 - \dfrac{1}{p_k}) \)

この他に以下の式が成り立ちます。

[ファイ関数の和]
\(\displaystyle \sum_{d|n}^{} \varphi(d) = n\)

[オイラーの定理]
\(a^{\varphi(n)} \equiv 1 \pmod n\)

ファイ関数の和は、\(n\) の約数を \(d\) とすると、\(\varphi(d)\) の合計値を求めることです。たとえば、8 の約数は 1, 2, 4, 8 の 4 通りありますが、\(\varphi(1) + \varphi(2) + \varphi(4) + \varphi(8)\) を計算すると、1 + 1 + 2 + 4 = 8 になります。

証明の概略を示します。ファイ関数の和を求める関数を \(F(n)\) とします。

\(n\) が素数の場合
\( F(n) = \varphi(1) + \varphi(n) = 1 + n - 1 = n \)

\(n = p^k\) (p は素数) の場合、約数は \(1, p, p^2, \ldots, p^k\) だから
\( F(p^k) = \displaystyle \sum_{i=0}^k \varphi(p^k) = 1 + (p - 1) + (p^2 - p) + \cdots + (p^{k-1} - p^{k-2}) + (p^k - p^{k-1}) = p^k \)

\(n = pq\) (\(p, q\) は素数) の場合、約数は \(1, p, q, pq\) だから
\(\begin{eqnarray} F(pq) &=& \varphi(1) + \varphi(p) + \varphi(q) + \varphi(pq) \\ &=& \varphi(1) + \varphi(p) + \varphi(q) + \varphi(q)\varphi(q) \\ &=& 1 + (p - 1) + (q - 1) + (p - 1)(q - 1) \\ &=& pq \\ F(pq) &=& F(p)F(q) = pq \end{eqnarray}\)

関数 \(F(n)\) の乗法性を認めることにして、
\(n = {p_i}^a \times {p_j}^b \times \cdots \times {p_k}^c\) と素因数分解できた場合
\( \begin{eqnarray} F(n) &=& F({p_i}^a \times {p_j}^b \times \cdots \times {p_k}^c) \\ &=& F({p_i}^a) \times F({p_j}^b) \times \cdots \times F({p_k}^c) \\ &=& {p_i}^a \times {p_j}^b \times \cdots \times {p_k}^c \\ &=& n \end{eqnarray} \)

オイラーの定理で n が素数の場合が「フェルマーの小定理」になります。

詳しい説明は 参考 URL 3, 7 をお読みください。

●メビウス関数

メビウス関数 (Möbius function) は、正の整数 n を与えると -1, 0, 1 のいずれかの値を返します。

\(\mu(1) = 1\)
n が平方因子を持つとき \(\mu(n) = 0\)
それ以外の場合 \(\mu(n) = (-1)^k\) (k は異なる素因子の個数)

メビウス関数 \(\mu(n)\) は引数 n が 1 の場合は 1 を返します。1 より大きい場合、n を素因数分解した結果で値が決まります。同じ素数で 2 回割り切れる (平方因子を持つ) 場合は 0 を返します。それ以外の場合、n は異なる素数の積で表されるので、その個数 k が奇数ならば -1 を、偶数ならば 1 を返します。

たとえば、24 は \(2^3 \times 3\) と素因数分解できますが、2 で 2 回割り切れるので \(\mu(24)\) は 0 になります。つまり、素因数分解して 2 以上の指数がある場合は 0 を返します。\(\mu(30)\) は \(30 = 2 \times 3 \times 5\) なので、\((-1)^3 = -1\) を返します。n が素数の場合も -1 になります。\(\mu(35)\) は \(35 = 5 \times 7\) なので、\((-1)^2 = 1 \) を返します。

●メビウス関数の性質

\(n\) の約数を \(d\) とすると、\(n \ne 1\) のとき \(\mu(d)\) の合計値は 0 になります。

\( \displaystyle \sum_{d|n}^{} \mu(d) = 0 \quad (n \neq 1) \)

●メビウス関数の反転公式

自然数 n を引数に受け取り、数を返す関数 \(f(n), g(n)\) を考えます。

\(\begin{array}{ll} 1. & g(n) = \displaystyle \sum_{d|n} f(d) \\ 2. & f(n) = \displaystyle \sum_{d|n} \mu(\frac{n}{d}) g(d) = \sum_{d|n} \mu(d) g(\frac{n}{d}) \end{array}\)

式 1 を満たす場合、式 2 が成り立ちます。これを「メビウスの反転公式」といいます。式 2 の場合、d は n の約数なので、n / d も n の約数です。d が決まれば n / d は一意に定まるので、式 2 の \(\mu(n/d) g(d)\) の和と \(\mu(d) g(n/d)\) の和は等しくなります。たとえば、n = 6 とすると、約数は 1, 2, 3, 6 の 4 通りあります。式 2 を計算すると、以下のように総和は等しくなることがわかります。

\(\begin{eqnarray} \displaystyle \sum_{n|d} \mu(\frac{n}{d}) g(d) = \mu(6)g(1) + \mu(3)g(2) + \mu(2)g(3) + \mu(1)g(6) \\ \displaystyle \sum_{n|d} \mu(d) g(\frac{n}{d}) = \mu(1)g(6) + \mu(2)g(3) + \mu(3)g(2) + \mu(6)g(1) \end{eqnarray}\)

詳しい説明は 参考 URL 4, 8 をお読みくださいませ。

簡単な例として、ファイ関数の和の式にメビウスの反転公式を適用してみましょう。

[ファイ関数の和]

\( \displaystyle \sum_{d|n} \varphi(d) = n \)

メビウスの反転公式を適用すると

\( \varphi(n) = \displaystyle \sum_{d|n} \varphi(\frac{n}{d}) \times d \)

実際に \(\varphi(n)\) を計算することができるのか、Python3 で試してみましょう。

>>> def phi(n):
...     return sum(mobius(n // d) * d for d in divisors(n))

>>> phi(1000)
400
>>> totient(1000)
400
>>> phi(12345)
6576
>>> totient(12345)
6576

phi() と totient() は同じ値を返します。メビウスの反転公式は正しいことがわかります。

●参考 URL

  1. 合同式(mod)の意味とよく使う6つの性質, (マスオさん)
  2. フェルマーの小定理の証明と例題, (マスオさん)
  3. オイラーのファイ関数のイメージ, (マスオさん)
  4. メビウスの反転公式の証明と応用, (マスオさん)
  5. フェルマーの小定理 - Wikipedia
  6. 約数関数 - Wikipedia
  7. オイラーのφ関数 - Wikipedia
  8. メビウス関数 - Wikipedia

Copyright (C) 2024 Makoto Hiroi
All rights reserved.

[ Home | Math ]