1 条题解

  • 0
    @ 2025-7-9 18:52:37

    方法思路

    1. 核心思想:枚举每个账号作为特殊账号(贡献ai粉丝),其余账号贡献⌊ai/2⌋粉丝
    2. 算法步骤
      • 尝试每个账号作为特殊账号
      • 如果特殊账号粉丝数恰好为x,直接返回1
      • 否则,贪心选择其他账号(按贡献值从大到小)直到恰好达到目标x
      • 同时考虑不使用特殊账号的情况
      • 取所有可行方案中使用账号数最少的方案
    3. 贪心策略:固定特殊账号后,优先选择贡献值大的普通账号,以最小化总账号数

    代码实现

    Java
    import java.util.*;
    
    public class Main {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            int n = scanner.nextInt();
            int x = scanner.nextInt();
            
            int[] fans = new int[n];
            for (int i = 0; i < n; i++) {
                fans[i] = scanner.nextInt();
            }
            
            System.out.println(minAccounts(n, x, fans));
            scanner.close();
        }
        
        private static int minAccounts(int n, int x, int[] fans) {
            int minCount = Integer.MAX_VALUE;
            
            // 尝试每个账号作为特殊账号
            for (int i = 0; i < n; i++) {
                int special = fans[i];  // 特殊账号的全部粉丝数
                
                // 如果特殊账号恰好满足需求
                if (special == x) {
                    return 1;
                }
                
                // 如果特殊账号不够,需要其他账号辅助
                if (special < x) {
                    // 计算还需要的粉丝数
                    int need = x - special;
                    
                    // 其他账号的贡献(每个贡献ai/2)
                    List<Integer> others = new ArrayList<>();
                    for (int j = 0; j < n; j++) {
                        if (j != i) {
                            others.add(fans[j] / 2);
                        }
                    }
                    
                    // 按贡献从大到小排序
                    Collections.sort(others, Collections.reverseOrder());
                    
                    // 贪心选择其他账号
                    int count = 1;  // 已经选择了特殊账号
                    int total = 0;
                    for (int contrib : others) {
                        if (total + contrib <= need) {
                            total += contrib;
                            count++;
                            if (total == need) {  // 恰好满足
                                minCount = Math.min(minCount, count);
                                break;
                            }
                        }
                    }
                }
            }
            
            // 尝试不使用特殊账号,所有账号都贡献ai/2
            List<Integer> contributions = new ArrayList<>();
            for (int f : fans) {
                contributions.add(f / 2);
            }
            
            Collections.sort(contributions, Collections.reverseOrder());
            
            int total = 0;
            int count = 0;
            for (int contrib : contributions) {
                total += contrib;
                count++;
                if (total == x) {  // 恰好满足
                    minCount = Math.min(minCount, count);
                    break;
                }
                if (total > x) {  // 超过了,不可能恰好满足
                    break;
                }
            }
            
            return minCount != Integer.MAX_VALUE ? minCount : -1;
        }
    }
    
    
    Python
    def min_accounts(n, x, fans):
        # 尝试使用特殊账号(贡献全部粉丝)
        min_count = float('inf')
        
        # 尝试每个账号作为特殊账号
        for i in range(n):
            special = fans[i]  # 特殊账号的全部粉丝数
            
            # 如果特殊账号恰好满足需求
            if special == x:
                return 1
            
            # 如果特殊账号不够,需要其他账号辅助
            if special < x:
                # 计算还需要的粉丝数
                need = x - special
                
                # 其他账号的贡献(每个贡献ai/2)
                others = []
                for j in range(n):
                    if j != i:
                        others.append(fans[j] // 2)
                
                # 按贡献从大到小排序
                others.sort(reverse=True)
                
                # 贪心选择其他账号
                count = 1  # 已经选择了特殊账号
                total = 0
                for contrib in others:
                    if total + contrib <= need:
                        total += contrib
                        count += 1
                        if total == need:  # 恰好满足
                            min_count = min(min_count, count)
                            break
        
        # 尝试不使用特殊账号,所有账号都贡献ai/2
        contributions = [f // 2 for f in fans]
        contributions.sort(reverse=True)
        
        total = 0
        count = 0
        for contrib in contributions:
            total += contrib
            count += 1
            if total == x:  # 恰好满足
                min_count = min(min_count, count)
                break
        
        return min_count if min_count != float('inf') else -1
    
    # 读取输入
    n, x = map(int, input().split())
    fans = list(map(int, input().split()))
    
    # 输出结果
    print(min_accounts(n, x, fans))
    
    
    C++
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <climits>
    using namespace std;
    
    int minAccounts(int n, int x, vector<int>& fans) {
        int minCount = INT_MAX;
        
        // 尝试每个账号作为特殊账号
        for (int i = 0; i < n; i++) {
            int special = fans[i];  // 特殊账号的全部粉丝数
            
            // 如果特殊账号恰好满足需求
            if (special == x) {
                return 1;
            }
            
            // 如果特殊账号不够,需要其他账号辅助
            if (special < x) {
                // 计算还需要的粉丝数
                int need = x - special;
                
                // 其他账号的贡献(每个贡献ai/2)
                vector<int> others;
                for (int j = 0; j < n; j++) {
                    if (j != i) {
                        others.push_back(fans[j] / 2);
                    }
                }
                
                // 按贡献从大到小排序
                sort(others.begin(), others.end(), greater<int>());
                
                // 贪心选择其他账号
                int count = 1;  // 已经选择了特殊账号
                int total = 0;
                for (int contrib : others) {
                    if (total + contrib <= need) {
                        total += contrib;
                        count++;
                        if (total == need) {  // 恰好满足
                            minCount = min(minCount, count);
                            break;
                        }
                    }
                }
            }
        }
        
        // 尝试不使用特殊账号,所有账号都贡献ai/2
        vector<int> contributions;
        for (int f : fans) {
            contributions.push_back(f / 2);
        }
        
        sort(contributions.begin(), contributions.end(), greater<int>());
        
        int total = 0;
        int count = 0;
        for (int contrib : contributions) {
            total += contrib;
            count++;
            if (total == x) {  // 恰好满足
                minCount = min(minCount, count);
                break;
            }
            if (total > x) {  // 超过了,不可能恰好满足
                break;
            }
        }
        
        return minCount != INT_MAX ? minCount : -1;
    }
    
    int main() {
        int n, x;
        cin >> n >> x;
        
        vector<int> fans(n);
        for (int i = 0; i < n; i++) {
            cin >> fans[i];
        }
        
        cout << minAccounts(n, x, fans) << endl;
        
        return 0;
    }
    
    
    • 1

    信息

    ID
    44
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    4
    已通过
    1
    上传者