绝对不需要计算 3 x n^3 余弦值。
我们可以假设 x ≤ y ≤ z。因此 x 可以是 1 到 n/3 范围内的任何整数。 y 可以是从 x 到 (n - x) / 2 范围内的任何整数。z 必须等于 n - x - y。仅此一项就可以将您尝试的三元组 (x, y, z) 的数量从 n^3 减少到大约 n^2 / 6。
接下来假设您找到三个数字,总数为 2.749。您尝试使用余弦 (x) = 0.748 的 x。任何涉及此 x 的总数都不能超过 2.748,因此您可以完全拒绝 x。一旦你找到一个好的总和,你就可以拒绝 x 的许多值。
为了使这更有效,您将值 x 从 cosine(x) 的最高值到最低值排序,因为这样您更有可能找到一个较高的总和,从而可以删除更多的值。
计算 cos(x) 很慢,因此您将值存储到表中。
所以:
Set c[i] = cos (i) for 1 ≤ i ≤ n.
Set x[i] = integers 1 to n/3, sorted in descending order by value of c[i].
Set (bestx, besty, bestz) = (1, 1, n-2) and total = c[bestx] + c [besty] + c [bestz].
for x = elements of array x where c[x] + 2 ≥ bestTotal
for y = x to (n-x)/2
z = n - x - y
total = c[x] + c[]y] + c[z]
if total > bestTotal
(bestx, besty, bestz) = (x, y, z)
bestTotal = total
您可以通过一些数学来改进这一点。如果 y + z 的总和是常数,就像这里的 y + z = n - x,则 cos(y) + cos (z) 的总和是有限的。令 P 为最接近 (n - x) / 2pi 的整数,令 d = (n - x) - P * 2pi,则 cos (y) + cos (z) 的最大可能和为 2 * cos (d /2)。
所以对于每个 x,1 ≤ x ≤ n/3,我们计算这个值 d 和 cos (x) + 2 * cos (d/2),将这些值存储为一些 x 可以达到的最大总和,对 x 进行排序,使这些值按降序排列,并忽略那些可实现的总数小于迄今为止的最佳总数的 x。
如果 n 真的很大(比如十亿),那么你可以使用欧几里德算法快速找到所有接近 2k*pi + d 的整数 y,但这会有点复杂。
for x in 1 to n/3
let s = n - x
let P = s / 2pi, rounded to the nearest integer
let d = (s - P * 2pi) / 2
let maxSum [x] = cos(x) + 2*cos(d)
Set x[i] = integers 1 to n/3, sorted in descending order by value of maxSum[i].
Set (bestx, besty, bestz) = (1, 1, n-2)
Set bestTotal = c[bestx] + c [besty] + c [bestz].
for x = elements of array x where maxSum[x] ≥ bestTotal
for y = x to (n-x)/2
z = n - x - y
total = c[x] + c[]y] + c[z]
if total > bestTotal
(bestx, besty, bestz) = (x, y, z)
bestTotal = total
附言。我实际上尝试了一些大约 1 亿的 N 值。事实证明,我可以对数组进行排序以首先尝试最有希望的 x 值,这需要很长时间,但通常 x 的第一个值是唯一被尝试的值。或者我可以使用 x = 1、2、3 等,这意味着将尝试几十个 x 值,这比排序更快。