Files
SolutionEuler/solutions/0052.PermutedMultiples/README.md

68 lines
2.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

欧拉计划第52题(**排列倍数**)的答案是 **142857**。
最快的数学计算方式基于以下**三大核心数学原理**的级联优化:
---
### 1. 位数约束原理(范围剪枝)
**数学基础**:若 $x$ 与 $6x$ 位数相同,则必须满足:
$$10^{n-1} \leq x < \frac{10^n}{6} \approx 1.666... \times 10^{n-1}$$
这直接排除了 $60\%$ 以上的搜索空间。例如6位数时,只需检查 $[100000, 166666)$ 区间,而非 $[100000, 1000000)$。
---
### 2. 模9同余原理(整除筛选)
**数学基础**:数字和与模9同余(数根理论)。若 $x$ 与 $kx$ 是数字排列,则:
$$\sum \text{digits}(x) \equiv x \pmod{9} \equiv kx \equiv \sum \text{digits}(kx) \pmod{9}$$
由此推出 $(k-1)x \equiv 0 \pmod{9}$。取 $k=2$,得:
$$x \equiv 0 \pmod{9}$$
**关键优化**:只需检查9的倍数,搜索空间再缩减 $89\%$。
---
### 3. 规范形签名原理(排列判定)
**数学基础**:两个数是排列 ⟺ 它们的**数字频数向量**(Digit Histogram)相同。
不采用字符串排序($O(d \log d)$),而是用**计数数组**作为规范签名($O(d)$):
```python
def signature(n):
count = [0] * 10
while n:
count[n % 10] += 1
n //= 10
return tuple(count) # 如142857 → (1,1,1,1,1,1,0,1,0,0)的某种编码
```
---
### 最优算法实现(Python)
```python
def euler52():
n = 1
while True:
start = 10**(n-1)
# 核心约束:x * 6 必须仍是n位数
end = int(10**n / 6) + 1
# 步长为9:利用模9同余原理
for x in range((start + 8) // 9 * 9, end, 9):
sig = signature(x)
# 检查2x到6x是否共享相同签名
if all(signature(k * x) == sig for k in range(2, 7)):
return x
n += 1
# 结果:142857(即1/7的小数循环节)
```
**复杂度**:对于 $n$ 位数,候选量从 $9 \times 10^{n-1}$ 降至约 $0.074 \times 10^{n-1}$,配合 $O(n)$ 的签名比较,可在**微秒级**求解。
---
### 深层数学结构
解 **142857** 并非偶然,它是**循环数**(Cyclic Number),与 $1/7 = 0.\overline{142857}$ 的小数展开密切相关。其性质源于 $10$ 是模 $7$ 的原根,导致 $2/7, 3/7...6/7$ 的循环节恰好是 $142857$ 的轮换排列。