查看: 8|回复: 0

GESP五级算法题解:小杨的幸运数字(洛谷B3929)代码分析...

[复制链接]
  • TA的每日心情
    无聊
    昨天 10:23
  • 签到天数: 52 天

    [LV.5]常住居民I

    51

    主题

    0

    回帖

    86

    积分

    注册会员

    Rank: 2

    积分
    86
    发表于 昨天 10:29 | 显示全部楼层 |阅读模式
    一、题目解读
    洛谷题目B3929“小杨的幸运数字”要求处理一系列查询数字x,将其转化为≥x的最小幸运数字。幸运数字定义为:≥a的完全平方数的倍数。题目难点在于高效判断和生成幸运数,避免超时。
    二、解题思路
    采用“预生成+哈希表”策略:
    1. 分步生成:先找出≥a的所有完全平方数(超级幸运数),再生成其倍数(幸运数)。
    2. 哈希加速:使用unordered_set存储幸运数,实现O(1)查询。
    3. 边界优化:通过预处理查询数组的最大值,缩小生成范围,避免无效计算。
    三、解题步骤
    1. 输入与预处理:读取N个查询,记录最大值max_x,并预留1000缓冲避免边界溢出。
    2. 生成幸运数集合:调用generateLuckyNumbers(a, max_x+1000),分两层循环生成超级幸运数及其倍数,存入哈希集。
    3. 查询处理:若x本身为幸运数直接输出;否则通过makeLucky(x)循环递增查找第一个幸运数。
    四、代码与注释
    1. #include iostream  
    2. #include vector  
    3. #include cmath  
    4. #include unordered_set  
    5. using namespace std;  

    6. // 生成幸运数集合(超级幸运数+倍数)  
    7. unordered_set<int> generateLuckyNumbers(int a, int max_x) {  
    8.     unordered_set<int> lucky_numbers;  
    9.     for (int i = ceil(sqrt(a)); i <= max_x; i++) {  // 从a的平方根开始找完全平方数  
    10.         int super_lucky = i * i;  
    11.         lucky_numbers.insert(super_lucky);  
    12.         for (int j = 2; super_lucky * j <= max_x; j++) {  // 生成倍数  
    13.             lucky_numbers.insert(super_lucky * j);  
    14.         }  
    15.     }  
    16.     return lucky_numbers;  
    17. }  

    18. // 查找比x大的最小幸运数  
    19. int makeLucky(int x, const unordered_set<int>& lucky_numbers) {  
    20.     while (true) {  
    21.         if (lucky_numbers.count(x)) return x;  // 若x在集合中直接返回  
    22.         x++;  
    23.     }  
    24. }  

    25. int main() {  
    26.     int a, N;  
    27.     cin >> a >> N;  
    28.     vector<int> queries(N);  
    29.     int max_x = 0;  
    30.     for (int i = 0; i < N; i++) {  
    31.         cin >> queries[i];  
    32.         if (queries[i] > max_x) max_x = queries[i];  
    33.     }  
    34.     unordered_set<int> lucky_numbers = generateLuckyNumbers(a, max_x + 1000);  // 生成幸运数集合  
    35.     for (int x : queries) {  
    36.         if (lucky_numbers.count(x)) {  
    37.             cout << "lucky" << endl;  
    38.         } else {  
    39.             cout << makeLucky(x, lucky_numbers) << endl;  
    40.         }  
    41.     }  
    42.     return 0;  
    43. }
    复制代码


    五、总结
    本解法通过“预生成+哈希表”将时间复杂度优化至O(N+√a),空间复杂度O(幸运数数量)。关键在于:
    1. 精准控制生成范围,避免冗余计算;
    2. 利用哈希表快速判断幸运数;
    3. 缓冲处理防止边界问题。
    该策略适用于大规模数据的高效处理,是解决此类数学分类问题的典型思路。

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表