#P1525. 第3题-小美乘除
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 441
            Accepted: 48
            Difficulty: 4
            
          
          
          
                       所属公司 : 
                              美团
                                
            
                        
              时间 :2023年9月2日
                              
                      
          
 
- 
                        算法标签>思维          
 
第3题-小美乘除
思路:思维
记大于 a0 的数有 x 个
- 
如果 x>1 ,则让 a0 乘 2 。
令 b 为大于 a0 的数构成的数组,cnti 为 bi 降到小于等于 a0 的次数。假设每个数都 bi 都满足 a0+1≤bi≤2a0
那么要使得每个数都小于等于 a0 ,选择乘法只需要 1 次,选择除法需要 x 次,x>1 。
 - 
如果 x=1 ,则让那个数除 2 下取整。 因为考虑 a0=3 ,大于 a0 的数为 7 。
此时让 a0 乘 2 为 6 仍然小于 7. 而让 7 除 2 下取整为 3 ,此时 a0=⌊27⌋ 。
 
时间复杂度:O(nlogn)
代码
c++
#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i];
    priority_queue<int, vector<int>, greater<int>> q;
    for (int i = 1; i < n; ++i)
        if (a[i] > a[0]) q.push(a[i]);
    int ans = 0;
    while (!q.empty()) {
        if (q.size() > 1) {
            ans += 1;
            a[0] *= 2;
            while (!q.empty() && q.top() <= a[0]) q.pop();
        } else {
            int t = q.top();
            q.pop();
            while (t > a[0]) {
                ans += 1;
                t /= 2;
            }
        }
    }
    cout << ans << "\n";
     
    return 0;
}
python
n = int(input())
nums = list(map(int, input().split()))
from collections import *
def solve(n, nums):
    res = 0
    candi = nums[0]
    nums = nums[1:]
    nums.sort()
    stack = deque()
    for i in range(0, n-1):
        if nums[i] > candi:
            stack.append(nums[i])
    if len(stack) == 0:
        return 0
    while stack:
        if len(stack) > 1:
            candi *= 2
            res += 1
            while stack and stack[0] <= candi:
                stack.popleft()
        else:
            t = stack.popleft()
            while t > candi:
                res += 1
                t //= 2
    return res
print(solve(n, nums))
java
import java.util.*;
class Main{
    static int res;
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int count = scanner.nextInt();
        scanner.nextLine();
        int[] cnt = new int[count];
        for(int i = 0; i < count; i++){
            cnt[i] = scanner.nextInt();
        }
        int a0 = cnt[0];
        int x = compareBig(cnt, a0);
        while(x > 1){
            cnt[0] *= 2;
            x = compareBig(cnt, cnt[0]);
            res++;
        }
        if(x == 0){
            System.out.println(res);
            return;
        }
        a0 = cnt[0];
        Arrays.sort(cnt);
        int b0 = cnt[cnt.length - 1];
        while(b0 >= 2 * a0){
            b0 /= 2;
            res++;
        }
        if(a0 + 1 <= b0){
            res++;
        }
        System.out.println(res);
    }
    public static int compareBig(int[] nums, int a0){
        int res = 0;
        for(int i = 1; i < nums.length; i++){
            if(nums[i] > a0){
                res++;
            }
        }
        return res;
    }
}
        题目描述
小美有一个长度为 n 的数组 a 。他需要将这个数组中第一个元素 a0 变成这个数组中的最大数。
小美有如下两种操作,
- 将 a0 乘 2
 - 选择一个 i(1≤i<n),使得 ai 变成 ⌊2ai⌋
 
现在小美问你,他至少要多少次操作才能使得 a0 变成最大数。
输入描述
第一行,一个正整数 n(1≤n≤105) ,代表数组的大小。
第二行输入 n 个正整数表示数组 a ,第 i 个数为 ai(1≤ai≤109) 。
输出描述
一个整数,表示使得 a0 变成最大数的最小操作次数
样例
输入
6
1 1 4 4 1 4
输出
2
说明
将 1 乘两次 2 。
Related
In following contests: