A098928:对 n × n × n n\times n\times n n×n×n 的三维立方点阵,问有多少立方体以其格点为顶点。
为了计算这个问题的答案,我们不妨先看看 2 2 2 维的情况。我们先考虑一个斜着摆的正方形,其边向量可以写作 ( a , b ) , ( b , − a ) , ( − a , − b ) , ( − b , a ) (a,b),(b,-a),(-a,-b),(-b,a) (a,b),(b,−a),(−a,−b),(−b,a)。考虑这个形状有多少种方法放进 n × n n\times n n×n 的点阵。这取决于它在 x , y x,y x,y 上的长度和宽度。无疑其长宽都是 a + b a+b a+b。那么对于被长宽为 h h h 框住的正方形有 h h h 种,而这样的正方形有 ( n − h ) 2 (n-h)^2 (n−h)2 种放法。所以答案就是 ∑ h h ⋅ ( n − h ) 2 \sum_h h \cdot (n-h)^2 ∑hh⋅(n−h)2。
对于三维情况,我们发现有一个很大的问题:三个维度的宽度可以是不一样的,比如 ( 3 , 4 , 0 ) , ( 4 , − 3 , 0 ) , ( 0 , 0 , 5 ) (3,4,0),(4,-3,0),(0,0,5) (3,4,0),(4,−3,0),(0,0,5) 支成的立方体。我们需要用比较聪明的方法枚举这三条棱。具体来说,需要满足条件:
向量 u , v , w \mathbf{u,v,w} u,v,w 两两正交( u ⋅ v = 0 \mathbf{u\cdot v = 0} u⋅v=0)且等长 ∣ u ∣ = ∣ v ∣ = ∣ w ∣ |\mathbf{u}|=|\mathbf v| = |\mathbf w| ∣u∣=∣v∣=∣w∣。
对于这样的一组解,它有 ( n − ∣ u x ∣ − ∣ v x ∣ − ∣ w x ∣ ) ⋅ ( n − ∣ u y ∣ − ∣ v y ∣ − ∣ w y ∣ ) ⋅ ( n − ∣ u z ∣ − ∣ v z ∣ − ∣ w z ∣ ) (n - |u_x| - |v_x| - |w_x|) \cdot (n - |u_y| - |v_y| - |w_y|) \cdot (n - |u_z| - |v_z| - |w_z|) (n−∣ux∣−∣vx∣−∣wx∣)⋅(n−∣uy∣−∣vy∣−∣wy∣)⋅(n−∣uz∣−∣vz∣−∣wz∣) 种放置方法(前提是各项均 > 0 >0 >0)。
接 yhx-12243 的论述,我们知道可以借助 Hurwitz 四元数 H = { s ω + x i + y j + z k ∣ s , x , y , z ∈ Z } , ω = 1 + i + j + k 2 H=\left\{ s \omega + x \mathrm i + y \mathrm j + z \mathrm k \mid s,x,y,z\in \mathbb Z \right\}, \omega = \frac{1+\mathrm i + \mathrm j + \mathrm k}{2} H={sω+xi+yj+zk∣s,x,y,z∈Z},ω=21+i+j+k 来枚举这样的向量组。
具体来说,对于每个 q ∈ H q\in H q∈H,考虑 v = x i + y j + z k v = x \mathrm i + y \mathrm j + z \mathrm k v=xi+yj+zk 被共轭作用 v ↦ q v q ‾ v \mapsto qv\overline q v↦qvq 确定了一个伸缩旋转。具体来说,首先是进行了旋转 v ↦ q v q − 1 v \mapsto q v q^{-1} v↦qvq−1,然后伸长了 ∣ q v q ‾ ∣ / ∣ v ∣ = ∣ q ∣ 2 |qv\overline q| / |v| = |q|^2 ∣qvq∣/∣v∣=∣q∣2 倍,也就是 q q q 的范数。但这并没有覆盖所有的变换,再引入无平方因子的奇数 r r r,所有的 ( r , q ) (r,q) (r,q) 构成的 v ↦ r ⋅ q v q ‾ v \mapsto r\cdot qv\overline q v↦r⋅qvq 精确覆盖了所有情况。
我们可以直接枚举 r ∣ q ∣ 2 ≤ n r |q|^2 \le n r∣q∣2≤n 的 ( r , q ) (r,q) (r,q),由于 ∣ q ∣ 2 ≤ n |q|^2\le n ∣q∣2≤n 的 Hurwitz 四元数只有 O ( n 2 ) O(n^2) O(n2) 种,那么再枚举 r r r 之后仍然只有 ∑ r ( n / r ) 2 = O ( n 2 ) \sum_r (n/r)^2 = O(n^2) ∑r(n/r)2=O(n2) 种。因此枚举的总时间为 O ( n 2 ) O(n^2) O(n2)。(这还是比较反直觉的,因为这说明起手 O ( n 3 ) O(n^3) O(n3) 枚举其中一条棱的做法走不通!)
这是一份 代码。加个前缀和优化稍微改改就能在几分钟内跑出 n ≤ 1 0 4 n\le 10^4 n≤104 的所有答案。
它还有很大的优化空间,因为一个立方体被从每个顶点数了三次,也就是枚举自带了一个 24 24 24 倍的常数。这对应于 ∣ q ∣ = 1 |q|=1 ∣q∣=1 的 Hurwitz 四元数总共有 24 24 24 种。如果能直接在 H / { ∣ ω ∣ = 1 ∣ ω ∈ H } H / \{ |\omega|=1\mid \omega\in H\} H/{∣ω∣=1∣ω∈H} 上枚举就可以去掉这个常数了。这里 是 yhx-12243 优化的版本。