# 2233. Maximum Product After K Increments
###### tags: `Leetcode` `Medium` `Math` `Greedy` `Priority Queue` `Smear Top Elements`
Link: https://leetcode.com/problems/maximum-product-after-k-increments/description/
## 思路
尽量把k加在比较小的数字上面才能得到optimal结果
### 思路一 Priority Queue $O(klogN)$
### 思路二 Smear Top Elements
我们需要将```K```都分配给较小的元素,尽量“共同富裕”。那么我们将```nums```排序之后,需要将```K```分配给前多少个较小元素呢?显然我们要找到一个位置```p```,使得前```p```个元素之和加上```K```之后再进行平均分配,依然达不到第```p+1```个元素. 为什么呢?如果前```p```个元素进行共产主义之后,均值大于了第```p+1```个元素,那为什么不在前```p+1```个元素内进行“共同富裕”呢,这样就有更多的元素可以趋近一致,从而使乘积更大化。
那么我们如何快速定位这个p呢?我们定义```diff```数组```diff[i] = presum[i]-nums[i]*(i+1)```,表明将前```i+1```个元素都提升至与```nums[i]```相等的话,需要多少“支援”。可以知道,这个```diff```一定是递增的。于是我们可以用二分找到最大的```p```,使得恰好```diff[p]<=K```,意味着K的支援能够将```nums[0:p]```抹平,但是不足以将```nums[0:p+1]```抹平。
我们接下来的任务就是,我们先把```nums[0:p-1]```补到和```nums[0]```一样大 然后看```k```还剩多少 先平均分给```nums[0:p]```每个element ```k/p```这么多 接下来我们给前```k%p```个元素每个都加1即可
## Code
### 思路一 Priority Queue
```java=
class Solution {
public int maximumProduct(int[] nums, int k) {
Queue<Integer> pq = new PriorityQueue<>();
int n = nums.length;
for(int i=0; i<n; i++){
pq.add(nums[i]);
}
for(int i=0; i<k; i++){
pq.add(pq.poll()+1);
}
long ans = 1;
int mod = 1000000007;
while(!pq.isEmpty()){
ans = (ans*pq.poll())%mod;
}
return (int)ans;
}
}
```
### 思路二 Smear Top Elements
```java=
class Solution {
public int maximumProduct(int[] nums, int k) {
Arrays.sort(nums);
int n = nums.length;
long[] diff = new long[n];
long presum = 0;
for(int i=0; i<n; i++){
presum += nums[i];
diff[i] = (i+1)*(long)(nums[i])-presum;
}
int start = 0, end = n;
while(start<end){
int mid = start+(end-start)/2;
if(diff[mid]<=k) start = mid+1;
else end = mid;
}
//set all number before nums[start-1] equals to nums[start-1]
for(int i=0; i<start; i++){
k -= nums[start-1]-nums[i];
nums[i] = nums[start-1];
}
//increase nums[0:(start-1)]
//if k still larger than 0, increase first k%start elements by 1
int each = k/start;
int remain = k%start;
for(int i=0; i<start; i++){
nums[i] += each;
if(i<remain) nums[i] += 1;
}
long ans = 1;
int mod = 1000000007;
for(int i=0; i<n; i++){
ans = (ans*nums[i])%mod;
}
return (int)ans;
}
}
```