给你一个下标从 0 开始的整数数组 nums
,它表示英雄的能力值。如果我们选出一部分英雄,这组英雄的 力量 定义为:
i0
,i1
,...ik
表示这组英雄在数组中的下标。那么这组英雄的力量为max(nums[i0],nums[i1] ... nums[ik])2 * min(nums[i0],nums[i1] ... nums[ik])
。
请你返回所有可能的 非空 英雄组的 力量 之和。由于答案可能非常大,请你将结果对 109 + 7
取余。
题意就是求所有子序列的最大值的平方再乘以最小值,因此与顺序无关,先进行排序。
举例数组:[1 ,2, 3,4]
此题应该想到每个值的贡献度(枚举每个数作为最大值),具体思路如下:
从大数开始比较好想(我是这么想的)
举例4,作为最大值的情况有以下几种
4
1 4
2 4
3 4
1 2 4
1 3 4
2 3 4
1 2 3 4
换个顺序看
4
3 4
2 4
2 3 4
1 4
1 2 4
1 3 4
1 2 3 4
题中所述,只需要求每个子序列的最大值和最小值即可
那么有
ans(4) = 4 * 4 * 4 + 4 * 4 * 3 + 4 * 4 * 2 * 2 + 4 * 4 * 1 * 4
简化
ans(4) = 4 * 4 * (4 + 3 + 2 * 2 + 1 * 4)
直接猜下公式
对n来说
An = n ^2 * (n + (n - 1) * 2 ^ 0 + (n - 2) * 2 ^ 1 + (n - 3) * 2 ^ 2 + (n - 4) * 2 ^ 3 ...)
式中 n 均为nums[n]
哎,猜对了
之后直接上代码提交
public int sumOfPower(int[] nums) {
int n = nums.length;
long res = 0;
int mod = (int) (1e9 + 7);
Arrays.sort(nums);
for (int i = n - 1; i >= 0; i--) {
long n2 = (((long)nums[i] % mod) * ((long)nums[i] % mod)) % mod;
long sum = nums[i];
for (int j = i - 1, pow = 0; j >= 0; j--, pow++) {
sum += ((nums[j] % mod) * (Math.pow(2, pow) % mod)) % mod;
}
res += ((n2 % mod) * (sum % mod)) % mod;
}
res %= mod;
return (int) (res);
}
超时,发现数据范围过大,O2必然不能过
通过规律发现(自己发现的规律,大佬的那个规律更简单)
A1 = (nums[1])
A2 = (nums[2] + nums[1])
A3 = (nums[3] + nums[2] + 2^1 * nums[1]) = nums[3] + nums[2] + (2 * A2 - nums[2])
A4 = (nums[4] + nums[3] + 2^1 * nums[2] + 2^2 * nums[1]) = nums[4] + nums[3] + (2 * A3 - nums[3])
通过一个前缀数组存储
代码如下
public int sumOfPower(int[] nums) {
int mod = (int) (1e9 + 7);
int n = nums.length;
if (n == 1) return (int) (((((long)nums[0] * nums[0]) % mod) * nums[0]) % mod);
long res = 0;
Arrays.sort(nums);
long[] prev = new long[n];
prev[0] = nums[0] % mod;
prev[1] = (nums[1] % mod + nums[0] % mod) % mod;
for (int i = 2; i < n; i++) {
prev[i] = (nums[i] % mod + nums[i - 1] % mod + (2L * (prev[i - 1] - nums[i - 1])) % mod) % mod;
}
for (int i = n - 1; i >= 0; i--) {
long n2 = (((long) nums[i] % mod) * ((long) nums[i] % mod)) % mod;
long sum = prev[i];
res += ((n2 % mod) * (sum % mod)) % mod;
}
res %= mod;
return (int) (res);
}
ok,过了