背景
您是否注意过以下规律?
- 整数 n 的平方 n2 总是满足以下两个命题中的某一个
- n2≡0(mod3)
- n2≡1(mod3)
- 整数 n 的 4 次方 n4 总是满足以下两个命题中的某一个
- n4≡0(mod5)
- n4≡1(mod5)
- 整数 n 的 5 次方总是满足以下命题
- n5≡n(mod10)
这些规律的背后是否有更深层的原因呢?我们能否证明这些规律?本文对此进行探讨。
正文
用较小的质数进行试验
我们可以用较小的质数 p 进行一些试验。我想通过 Python 代码来自动生成下图展示的这种表格 ⬇️

python
"""
A tool for generating modular powers for a given prime number p.
"""
from typing import List
class SimpleModularPowDisplayer:
"""A class to display modular powers for a given positive integer m.
Attributes:
m (int): a positive integer (greater than or equal to 2)
"""
def __init__(self, m: int) -> None:
"""Initialize the displayer with a positive integer m.
Args:
m (int): a positive integer
Raises:
ValueError: when m is not an integer or m < 2
"""
if not isinstance(m, int) or m < 2:
raise ValueError("m must be an integer that is greater than or equal to 2")
self.m = m
def _get_header_elements(self) -> List[str]:
"""Generate the header elements for the Markdown table.
Returns:
List[str]: Header cells for the Markdown table (LaTeX-formatted)
"""
header = [f"$a$"]
for exp in range(2, self.m + 1):
header.append(f"$a^{{{exp}}} \\bmod {self.m}$")
return header
def print_header(self) -> None:
"""Print the header row of the Markdown table."""
elements = self._get_header_elements()
print(f"| {' | '.join(elements)} |")
def _get_row_elements(self, a: int) -> List[str]:
"""Generate the elements for a single row of the Markdown table.
Args:
a (int): the base number (0 <= a < m)
Returns:
List[str]: Cell values for the row (LaTeX-formatted)
"""
elements = [f"${a}$"]
current = a
for _ in range(2, self.m + 1):
current = (current * a) % self.m
elements.append(f"${current}$")
return elements
def print_row(self, a: int) -> None:
"""Print a single row of the Markdown table for a given base a.
Args:
a (int): an integer that satisfies the condition 0 <= a < m
Raises:
ValueError: If a is outside the range [0, m-1]
"""
if not 0 <= a < self.m:
raise ValueError(f"a should be inside [0, {self.m-1}]")
elements = self._get_row_elements(a)
print(f"| {' | '.join(elements)} |")
def show_markdown_result(self) -> None:
"""Print the complete Markdown table for modular powers of m."""
print(f"#### $m={self.m}$")
self.print_header()
# Print the separator row
separator = ["---"] * len(self._get_header_elements())
print(f"| {' | '.join(separator)} |")
# Traverse all numbers from 0 to m-1
for a in range(self.m):
self.print_row(a)
if __name__ == "__main__":
# A list with prime numbers
PRIME_LIST = [2, 3, 5, 7, 11]
for prime in PRIME_LIST:
try:
displayer = SimpleModularPowDisplayer(prime)
displayer.show_markdown_result()
print("\n")
except ValueError as e:
print(f"Error occurred when processing p={prime}: {e}")
请将上述代码保存为 print_markdown_table.py。用如下命令可以运行 print_markdown_table.py
bash
python3 print_markdown_table.py
运行结果包含了 5 个 markdown 表格 ⬇️
m=2
| a | a2mod2 |
|---|---|
| 0 | 0 |
| 1 | 1 |
m=3
| a | a2mod3 | a3mod3 |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
m=5
| a | a2mod5 | a3mod5 | a4mod5 | a5mod5 |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 1 | 1 |
| 2 | 4 | 3 | 1 | 2 |
| 3 | 4 | 2 | 1 | 3 |
| 4 | 1 | 4 | 1 | 4 |
m=7
| a | a2mod7 | a3mod7 | a4mod7 | a5mod7 | a6mod7 | a7mod7 |
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 2 | 4 | 1 | 2 | 4 | 1 | 2 |
| 3 | 2 | 6 | 4 | 5 | 1 | 3 |
| 4 | 2 | 1 | 4 | 2 | 1 | 4 |
| 5 | 4 | 6 | 2 | 3 | 1 | 5 |
| 6 | 1 | 6 | 1 | 6 | 1 | 6 |
m=11
| a | a2mod11 | a3mod11 | a4mod11 | a5mod11 | a6mod11 | a7mod11 | a8mod11 | a9mod11 | a10mod11 | a11mod11 |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 2 | 4 | 8 | 5 | 10 | 9 | 7 | 3 | 6 | 1 | 2 |
| 3 | 9 | 5 | 4 | 1 | 3 | 9 | 5 | 4 | 1 | 3 |
| 4 | 5 | 9 | 3 | 1 | 4 | 5 | 9 | 3 | 1 | 4 |
| 5 | 3 | 4 | 9 | 1 | 5 | 3 | 4 | 9 | 1 | 5 |
| 6 | 3 | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 | 6 |
| 7 | 5 | 2 | 3 | 10 | 4 | 6 | 9 | 8 | 1 | 7 |
| 8 | 9 | 6 | 4 | 10 | 3 | 2 | 5 | 7 | 1 | 8 |
| 9 | 4 | 3 | 5 | 1 | 9 | 4 | 3 | 5 | 1 | 9 |
| 10 | 1 | 10 | 1 | 10 | 1 | 10 | 1 | 10 | 1 | 10 |
找规律
通过观察以上 5 个 markdown 表格,我们可以发现一些规律 ⬇️ (也许您还能发现其他规律)
- 对满足 0<a<p 的整数 a 而言, a2k≡(p−a)2k(modp) 似乎总是成立 ( k 为任意正整数)
- 对满足 0<a<p 的整数 a 而言, ap−1≡1(modp) 似乎总是成立
我们试试证明它们。
规律一的证明
我们尝试证明以下规律
对满足 0<a<p 的整数 a 而言, a2k≡(p−a)2k(modp) 总是成立 ( k 为任意正整数, p 为任意质数)
k=1 的情况最简单,我们先看看它 ⬇️
a2−(p−a)2=a2−(p2−2pa+a2)=−p2+2pa
因此 p∣(a2−(p−a)2),所以 a2≡(p−a)2(modp)
如果我们能将以下 k 个等式左边右边各自相乘,就可以得到要证的等式 👉 a2k≡(p−a)2k(modp)
- a2≡(p−a)2(modp)
- a2≡(p−a)2(modp)
- ⋯
- a2≡(p−a)2(modp)
但是能否这样做乘法呢?答案是肯定的。
如果 x≡x′(modn) 和 y≡y′(modn) 成立,那么以下两个命题成立
- n∣(x−x′)
- n∣(y−y′)
也就是说,我们可以找到整数 a,b 使得以下两个等式成立
- x′=x+an
- y′=y+bn
所以 xy−x′y′=xy−(x+an)(y+bn)=−ayn−bxn−abn2,那么 n∣(xy−x′y′)
由此可见,在模 n 运算中,我们确实可以在 ≡ 运算两边做乘法。
于是 a2k≡(p−a)2k(modp) 对任意正整数 k 都成立。
规律二的证明
说明:本小节的证明来自 灵茶山艾府 所写的 分享丨模运算的世界:当加减乘除遇上取模(模运算恒等式/费马小定理/组合数) 一文(有改动)。由于其中所讲的都是经典的数学知识,我想其中的证明应该不存在版权问题,但引用其中的内容时,应该注明出处。于是我写了这么一段说明
我们的目标是,证明或者证伪以下命题
对 0<a<p 的整数 a 而言, ap−1≡1(modp)。
首先,对任意整数 x,y, (x+y)p 可以用二项式定理进行展开。
(x+y)p=i=0∑pCpixiyp−i
而 Cpi=i!(p−i)!p!
- 当 i=0 时, Cp0=1
- 当 0<i<p 时, p∣p! 成立,由算术基本定理可得, p∣Cpi
- 当 i=p 时, Cpp=1
所以
(x+y)p=i=0∑pCpixiyp−i
=Cp0yp+⋯+Cppxp
其中 ⋯ 所表示的各项均可被 p 整除。
于是我们可以得出
(x+y)p≡xp+yp(modp)
令 y=1 就会得到 (x+1)p≡xp+1(modp)。
当 x=0 时, 0p≡0(modp) 显然成立。假设 x=k 时, kp≡k(modp) 成立( k 是某个自然数)。也就是说, p∣(kp−k) 成立。
那么 x=k+1 时,
(k+1)p−(k+1)=kp+1+pN−(k+1)
其中 N 表示某个整数。继续化简,可以得到 ⬇️
(k+1)p−(k+1)=kp+pN−k=kp−k+pN
注意到以下两个命题成立
- p∣(kp−k)
- p∣pN
那么 p∣(kp−k+pN) 成立,也就是说, (k+1)p≡kp+1(modp) 成立。
运用数学归纳法,可以得到 xp≡x(modp) 对任意自然数 x 都成立。
- 当 p∣x 时, xp≡0(modp) 显然成立
- 当 p∤x 时,由于 p∣(xp−x),那么 p∣x(xp−1−1)。由算术基本定理可得 p∣(xp−1−1),即 xp−1≡1(modp)。⬅️ 这就是费马小定理
费马小定理的简单应用
我们回到 背景 中所提到的 3 个问题
问题 1
- 整数 n 的平方 n2 是否总是满足以下两个命题中的某一个
- n2≡0(mod3)
- n2≡1(mod3)
- 当 3∣n 时, n2≡0(mod3) 显然成立
- 当 3∤n 时,由费马小定理可得, n2≡1(mod3)
问题 1 解决了
问题 2
- 整数 n 的 4 次方 n4 是否总是满足以下两个命题中的某一个
- n4≡0(mod5)
- n4≡1(mod5)
- 当 5∣n 时, n4≡0(mod5) 显然成立
- 当 4∤n 时,由费马小定理可得, n4≡1(mod5)
问题 2 解决了
问题 3
- 整数 n 的 5 次方是否总是满足以下命题
- n5≡n(mod10)
- 在费马小定理的基础上,可知 n5≡n(mod5),所以 5∣(n5−n) 成立
- 考虑到 n5 和 n 的奇偶性相同,那么 2∣(n5−n)
由算术基本定理可知,当 n>1 时, n5−n 的质因数分解结果是唯一的,那么这个分解结果中至少包含一个 2,至少包含一个 5。所以 10∣(n5−n)。而 n=0,1 时, 10∣(n5−n) 显然成立。所以对任意自然数 n 而言, 10∣(n5−n)。对负整数 n 来说, n5−n=−((−n)5−(−n))。那么对任意整数 n 而言, 10∣(n5−n) 成立。换句话说 n5≡n(mod10) 对任意整数 n 成立
问题 3 解决了