GESP2023年五级小杨的幸运数 从完全平方数到高效查询的完整指南C++实现(洛谷P3929)
一、题目分析
1.根据题目要求,我们需要处理两种操作:
判断一个数是否是幸运数(大于等于a的完全平方数或其倍数)
如果不是幸运数,则进行"幸运化"处理(找到比它大的最小幸运数)
2.解题思路:
预生成幸运数:提前计算所有可能的幸运数
高效查询:使用哈希集合存储幸运数以实现O(1)查询
幸运化处理:线性搜索比x大的最小幸运数
二、C++代码实现
#include <iostream>
#include <vector>
#include <cmath>
#include <unordered_set>
using namespace std;
// 预先生成所有超级幸运数(≥a的完全平方数)和幸运数(超级幸运数的倍数)
unordered_set<int> generateLuckyNumbers(int a, int max_x) {
unordered_set<int> lucky_numbers;
// 生成超级幸运数(≥a的完全平方数)
for (int i = ceil(sqrt(a)); i * i <= max_x; i++) {
int super_lucky = i * i;
lucky_numbers.insert(super_lucky);
// 生成该超级幸运数的所有倍数(幸运数)
for (int j = 2; super_lucky * j <= max_x; j++) {
lucky_numbers.insert(super_lucky * j);
}
}
return lucky_numbers;
}
// 幸运化处理:找到比x大的最小幸运数
int makeLucky(int x, const unordered_set<int>& lucky_numbers) {
while (true) {
if (lucky_numbers.count(x)) return x;
x++;
}
}
int main() {
int a, N;
cin >> a >> N;
// 读取所有查询数字,找出最大值以确定生成幸运数的范围
vector<int> queries(N);
int max_x = 0;
for (int i = 0; i < N; i++) {
cin >> queries[i];
if (queries[i] > max_x) max_x = queries[i];
}
// 生成幸运数集合(包含所有可能的幸运数,直到最大查询值)
unordered_set<int> lucky_numbers = generateLuckyNumbers(a, max_x + 1000); // 额外缓冲
// 处理每个查询
for (int x : queries) {
if (lucky_numbers.count(x)) {
cout << "lucky" << endl;
} else {
cout << makeLucky(x, lucky_numbers) << endl;
}
}
return 0;
}三、详细讲解
1. 幸运数生成
我们首先生成所有超级幸运数(≥a的完全平方数),然后生成它们的倍数:
unordered_set<int> generateLuckyNumbers(int a, int max_x) {
unordered_set<int> lucky_numbers;
// 生成超级幸运数
for (int i = ceil(sqrt(a)); i * i <= max_x; i++) { int super_lucky = i * i;
lucky_numbers.insert(super_lucky);
// 生成倍数
for (int j = 2; super_lucky * j <= max_x; j++) {
lucky_numbers.insert(super_lucky * j);
}
} return lucky_numbers;
}2. 幸运数判断
使用哈希集合的count方法快速判断:
if (lucky_numbers.count(x)) {
cout << "lucky" << endl;
}3. 幸运化处理
从x+1开始逐个检查,直到找到第一个幸运数:
int makeLucky(int x, const unordered_set<int>& lucky_numbers) { while (true) { if (lucky_numbers.count(x)) return x;
x++;
}
}四、复杂度分析
幸运数生成:O(k log k),k为幸运数数量
幸运数判断:O(1)
幸运化处理:平均O(m),m为到下一个幸运数的距离
原创内容 转载请注明出处

