📅  最后修改于: 2023-12-03 15:06:03.878000             🧑  作者: Mango
给定一个整数数组 arr 和一个整数数组 brr,以及一个整数 K。求 X 的最小值,使得 $\sum_{i=0}^{n-1}{(arr[i] - X)^{brr[i]}} \leq K$。
为了简化计算,我们可以将 $arr[i]$ 按非降序排序。此时,对于每个 $i$,如果对于所有满足 $j < i$ 的 $j$,均有 $arr[j] - X \leq arr[i] - X$,那么可以把 $arr[i]$ 看作是所有 $arr[j]$ 的下限。此时,如果 $X$ 越大,更新的值也越大,即更新函数是单调的。那么我们可以二分最优的 $X$。
假设我们要求二分左端点 $l$ 和右端点 $r$,二分过程中维护一个变量 $sum$(即 $\sum_{i=0}^{n-1}{(arr[i] - X)^{brr[i]}}$)。对于每次的二分尝试,如果 $sum \leq K$,则更新左端点 $l$;否则更新右端点 $r$。当 $r-l=1$ 时,即找到了最小的 $X$,再返回 $l$ 即可。
由于求幂操作是 $O(\log brr_i)$ 的,总的时间复杂度是 $O(n \log^2 n)$。可以通过将 log 小定值来进行优化。
def findX(arr, brr, K):
n = len(arr)
arr_brr = list(zip(arr, brr))
arr_brr.sort()
def calc_sum(x):
s = 0
for i in range(n):
s += (arr_brr[i][0] - x) ** arr_brr[i][1]
return s
l, r = arr_brr[0][0], arr_brr[-1][0]
while l < r - 1:
mid = (l + r) // 2
if calc_sum(mid) > K:
l = mid
else:
r = mid
if calc_sum(l) <= K:
return l
else:
return r