其他答案展示了方程的解析解:
k * (k + 1) = n * (n + 1) / 2 其中n已知
然而,问题是OP需要
k为整数,但并非每个选定的
n都存在这样的值。
我们可以使用整数算术将牛顿法调整为解决此方程。
sum_n = n * (n + 1) / 2
k = n
repeat indefinitely // It usually needs only a few iterations, it's O(log(n))
f_k = k * (k + 1)
if f_k == sum_n
k is the solution, exit
if f_k < sum_n
there's no k, exit
k_n = (f_k - sum_n) / (2 * k + 1) // Newton step: f(k)/f'(k)
if k_n == 0
k_n = 1 // Avoid inifinite loop
k = k - k_n;
这里有一个C++实现。
我们可以使用问题中发布的算法来找到所有满足方程式的(
n,
k)对,其中 0 <
k <
n ≤
N。
n = 1 // This algorithm compares 2 * k * (k + 1) and n * (n + 1)
sum_n = 1 // It finds all the pairs (n, k) where 0 < n ≤ N in O(N)
sum_2k = 1
for every n <= N // Note that n / k → sqrt(2) when n → ∞
while sum_n < sum_2k
n = n + 1 // This inner loop requires a couple of iterations,
sum_n = sum_n + n // at most.
if ( sum_n == sum_2k )
print n and k
k = k + 1
sum_2k = sum_2k + 2 * k
在
这里有一个C++实现,可以找到第一对满足
N < 200,000,000 的数对:
N K K * (K + 1)
----------------------------------------------
3 2 6
20 14 210
119 84 7140
696 492 242556
4059 2870 8239770
23660 16730 279909630
137903 97512 9508687656
803760 568344 323015470680
4684659 3312554 10973017315470
27304196 19306982 372759573255306
159140519 112529340 12662852473364940
当然,对于太大的值来说,这变得不切实际,并最终溢出。
此外,有一种
更好的方法来找到所有这些配对(你是否注意到了最后一位数字序列中的规律?)。
我们可以从操纵这个
丢番图方程开始。
2k(k + 1) = n(n + 1)
引入变量 u = n + 1 → n = u - 1,v = k + 1 → k = v - 1
2(v - 1)v = (u - 1)u
2(v
2 - v) = u
2 + u
2(4v
2 - 4v) = 4u
2 + 4u
2(4v
2 - 4v) + 2 = 4u
2 - 4u + 2
2(4v
2 - 4v + 1) = (4u
2 - 4u + 1) + 1
2(2v - 1)
2 = (2u - 1)
2 + 1
代入变量 x = 2u - 1 → u = (x + 1)/2,y = 2v - 1 → v = (y + 1)/2
2y
2 = x
2 + 1
x
2 - 2y
2 = -1
这是关于2的负
裴蜀定理。
通过观察,很容易找到它的基本解,
x1=1和
y1=1。这些对应于
n=
k=0的原二次不定方程的解,但不是原问题的解(我忽略了0项的求和)。
一旦这些已知,
我们可以用两个简单的递推关系计算出所有其他解:
xi+1 = xi + 2yi
yi+1 = yi + xi
请注意,我们需要“跳过”偶数的
y,因为它们会导致非整数解。因此我们可以直接使用这些解。
$x_{i+2} = 3x_i + 4y_i$ 可以翻译为 $u_{i+1} = 3u_i + 4v_i - 3$,$n_{i+1} = 3n_i + 4k_i + 3$;
$y_{i+2} = 2x_i + 3y_i$ 可以翻译为 $v_{i+1} = 2u_i + 3v_i - 2$,$k_{i+1} = 2n_i + 3k_i + 2$。
n k
-----------------------------------------------
3* 0 + 4* 0 + 3 = 3 2* 0 + 3* 0 + 2 = 2
3* 3 + 4* 2 + 3 = 20 2* 3 + 3* 2 + 2 = 14
3*20 + 4*14 + 3 = 119 2*20 + 3*14 + 2 = 84
...
K(K+1) = 1/2 * (N)(N+1)/2
关于K
的方程,然后你就能在常数时间内得到结果。 - 463035818_is_not_a_number