Project Euler 341
Project Euler 341
题目
Golomb’s self-describing sequence
The Golomb’s self-describing sequence \((G(n))\) is the only nondecreasing sequence of natural numbers such that \(n\) appears exactly \(G(n)\) times in the sequence. The values of \(G(n)\) for the first few \(n\) are
\[\begin{matrix} n & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 & 15 & \ldots \\ G(n) & 1 & 2 & 2 & 3 & 3 & 4 & 4 & 4 & 5 & 5 & 5 & 6 & 6 & 6 & 6 & \ldots \end{matrix}\]
You are given that \(G(10^3) = 86\), \(G(10^6) = 6137\).
You are also given that \(\sum G(n^3) = 153506976\) for \(1 \le n \lt 10^3\).
Find \(\sum G(n^3)\) for \(1 \le n \lt 10^6\).
解决方案
定义前缀和\(\displaystyle{F(m)=\sum_{i=1}^{m} G(i), F(0)=0.}\)
由于“整数 \(m\) 出现 \(G(m)\) 次”且序列非递减,所有值不超过 \(m\) 的项必然构成序列的最前一段,因此:
- 值为 \(m\) 的项,正好占据下标区间\((F(m-1)+1,F(m-1)+2,\dots,F(m)).\)
- 等价地,对任意下标 \(n\),\(G(n)=m \iff F(m-1)<n\le F(m).\)
这给出一个非常重要的“反演”描述:\(G(n)=\min\{m:F(m)\ge n\}.\)
接着定义一个加权前缀和\(\displaystyle{S(m)=\sum_{i=1}^{m} i\cdot G(i), S(0)=0.}\)
注意到序列前 \(F(m)\) 项的取值恰好是 \(1,2,\dots,m\),其中 \(i\) 出现 \(G(i)\) 次,因此前 \(F(m)\) 项的数值和为\(\displaystyle{\sum_{k=1}^{F(m)} G(k)=\sum_{i=1}^{m} i\cdot G(i)=S(m).}\)
而左侧正是 \(F\) 在点 \(F(m)\) 的取值,于是得到关键恒等式:\(F(F(m))=S(m).\)
固定一个 \(m\)。在下标区间\((F(m-1),F(m)]\)内,序列恒等于 \(m\),即 \(G(t)=m\)。因此 \(F(t)\) 在这段上每次增加 \(m\),并且起点为\(F(F(m-1))=S(m-1).\)
于是对任意 \(q=1,2,\dots,G(m),F(F(m-1)+q)=S(m-1)+m\cdot q.\)
也就是说,\(F\) 在这一整段上是严格等差的。现在要计算 \(G(N)\),根据 \(G(N)=\min\{t:F(t)\ge N\}\),如果我们找到唯一的 \(m\) 使得\(S(m-1)<N\le S(m),\)那么 \(N\) 必落在这段等差范围内。令 \(s=S(m-1)\),则最小的 \(q\) 满足\(s+m\cdot q\ge N\)为\(q=\left\lceil\dfrac{N-s}{m}\right\rceil.\)
对应的下标 \(t\)(也就是 \(G(N)\))为\(G(N)=F(m-1)+q.\)
这就是可以直接用于扫描的计算公式:若\(S(m-1)<N\le S(m)\),那么\(G(N)=F(m-1)+\left\lceil\dfrac{N-S(m-1)}{m}\right\rceil.\)
Golomb 序列有经典递推(可由“每个整数出现次数由自身给出”与上面的反演结构推导得到): \[G(1)=1,G(n)=1+G\bigl(n-G(G(n-1))\bigr), (n>1).\]
该递推只依赖更小下标的值,因此可以线性生成 \(G(1\dots M)\)。
最终,我们仅需要维护:
- \(G(m)\):当前递推得到;
- \(F(m) = F(m-1) + G(m)\);
- \(S(m) = S(m-1) + mG(m)\)。
每当某个 \(n\) 落入 \((S(m-1),S(m)]\),用\(q=\left\lceil\dfrac{N-S(m-1)}{m}\right\rceil\)并累加\(G(N)=F(m-1)+q.\)
代码
1 | from array import array |