1

GESP认证C++编程真题解析 | 202312 五级

​欢迎大家订阅我的专栏:算法题解:C++与Python实现
本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战!

专栏特色
1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的代码实现与详细指导,帮助您夯实算法基础。
2.系统化学习路径:按照算法类别和难度分级,从基础到进阶,循序渐进,帮助您全面提升编程能力与算法思维。

适合人群:

  • 准备参加蓝桥杯、GESP、CSP-J、CSP-S等信息学竞赛的学生
  • 希望系统学习C++/Python编程的初学者
  • 想要提升算法与编程能力的编程爱好者

附上汇总帖:GESP认证C++编程真题解析 | 汇总


编程题

B3929 小杨的幸运数

【题目来源】

洛谷:[B3929 GESP202312 五级] 小杨的幸运数 - 洛谷

【题目描述】

小杨认为,所有大于等于 \(a\) 的完全平方数都是他的超级幸运数。

小杨还认为,所有超级幸运数的倍数都是他的幸运数。自然地,小杨的所有超级幸运数也都是幸运数。

对于一个非幸运数,小杨规定,可以将它一直 \(+1\),直到它变成一个幸运数。我们把这个过程叫做幸运化。例如,如果 \(a=4\),那么 \(4\) 是最小的幸运数,而 \(1\) 不是,但我们可以连续对 \(1\)\(3\)\(+1\) 操作,使其变为 \(4\),所以我们可以说, \(1\) 幸运化后的结果是 \(4\)

现在,小杨给出 \(N\) 个数,请你首先判断它们是不是幸运数;接着,对于非幸运数,请你将它们幸运化。

【输入】

第一行 \(2\) 个正整数 \(a, N\)

接下来 \(N\) 行,每行一个正整数 \(x\) ,表示需要判断(幸运化)的数。

【输出】

输出 \(N\) 行,对于每个给定的 \(x\) ,如果它是幸运数,请输出 lucky,否则请输出将其幸运化后的结果。

【输入样例】

2 4
1 
4
5
9

【输出样例】

4
lucky
8
lucky

【算法标签】

《洛谷 B3929 小杨的幸运数》 #二分# #素数判断,质数,筛法# #GESP# #2023#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

const int N = 1100005;  // 最大范围
int a, n;               // a: 判断是否为完全平方数, n: 查询次数
int b[N];              // 存储每个数的结果

int main()
{
    // 输入a和n
    cin >> a >> n;
    
    // 计算sqrt(a)的上取整
    int x = sqrt(a);
    if (x * x != a)
    {
        x++;
    }
    
    // 预处理:标记所有完全平方数的倍数
    // 从x开始,遍历所有可能的平方数
    for (int i = x; i * i <= 1100000; i++)
    {
        // 将i*i的所有倍数标记为自身
        for (int j = i * i; j <= 1100000; j += i * i)
        {
            b[j] = j;  // 标记j是某个平方数的倍数
        }
    }
    
    // 预处理:填充未标记的位置
    // 从后向前扫描,记录最近遇到的正数
    x = 0;  // 这里重新使用x作为临时变量
    for (int i = 1100000; i >= 0; i--)
    {
        if (b[i])
        {
            x = b[i];  // 更新最近遇到的标记值
        }
        else
        {
            b[i] = x;  // 填充为最近的标记值
        }
    }
    
    // 调试输出,查看b数组前20个值
    // for (int i=1; i<=20; i++)
    //     cout << b[i] << " ";
    // cout << endl;
    
    // 处理n个查询
    for (int i = 1; i <= n; i++)
    {
        int t;
        cin >> t;  // 输入查询的数
        
        if (b[t] == t)
        {
            cout << "lucky" << endl;  // 是完全平方数的倍数
        }
        else
        {
            cout << b[t] << endl;  // 输出最近的大于等于t的标记值
        }
    }
    
    return 0;
}

【运行结果】

2 4
1
4
4
lucky
5
8
9
lucky

B3930 烹饪问题

【题目来源】

洛谷:[B3930 GESP202312 五级] 烹饪问题 - 洛谷

【题目描述】

\(N\) 种食材,编号从 \(1\)\(N\),其中第 \(i\) 种食材的美味度为 \(a_i\)

不同食材之间的组合可能产生奇妙的化学反应。具体来说,如果两种食材的美味度分别为 \(x\)\(y\) ,那么它们的契合度为 $x\ \text{and}\ y $。

其中,\(\text{and}\) 运算为按位与运算,需要先将两个运算数转换为二进制,然后在高位补足 ,再逐位进行与运算。例如,\(12\)\(6\) 的二进制表示分别为 \(1100\)\(0110\) ,将它们逐位进行与运算,得到 \(0100\) ,转换为十进制得到 4,因此 \(12\ \text{and}\ 6 = 4\)在 C++ 或 Python 中,可以直接使用 & 运算符表示与运算。

现在,请你找到契合度最高的两种食材,并输出它们的契合度。

【输入】

第一行一个整数 \(N\),表示食材的种数。

接下来一行 \(N\) 个用空格隔开的整数,依次为 \(a_1,\cdots,a_N\),表示各种食材的美味度。

【输出】

输出一行一个整数,表示最高的契合度。

【输入样例】

3
1 2 3

【输出样例】

2

【算法标签】

《洛谷 B3930 烹饪问题》 #贪心# #位运算# #GESP# #2023#

【代码详解】

// 40分版本
#include <bits/stdc++.h>
using namespace std;

const int N = 1000005;  // 最大数组长度
int n;                  // 数组元素个数
int maxn = -1e9;        // 最大与运算结果,初始化为极小值
int a[N];               // 存储输入数组

int main()
{
    // 输入数组大小
    cin >> n;
    
    // 输入数组元素
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    
    // 暴力枚举所有不相同的元素对
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            // 跳过相同的元素对
            if (i == j)
            {
                continue;
            }
            
            // 计算按位与并更新最大值
            maxn = max(maxn, a[i] & a[j]);
        }
    }
    
    // 输出最大的按位与结果
    cout << maxn << endl;
    
    return 0;
}
#include <bits/stdc++.h>
using namespace std;

const int N = 1000005;  // 最大数组长度
int n;                  // 数组元素个数
int maxn = -1e9;        // 最大与运算结果,初始化为极小值
int a[N];               // 存储输入数组

int main()
{
    // 输入数组大小
    cin >> n;
    
    // 输入数组元素
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    
    // 将数组从大到小排序
    sort(a + 1, a + n + 1, greater<int>());
    
    // 优化后的双重循环
    for (int i = 1; i <= n; i++)
    {
        // 剪枝:如果当前元素已经小于等于当前最大值,跳过
        if (a[i] <= maxn)
        {
            continue;
        }
        
        // 与后面的元素进行按位与运算
        for (int j = i + 1; j <= n; j++)
        {
            maxn = max(maxn, a[i] & a[j]);
        }
    }
    
    // 输出最大的按位与结果
    cout << maxn << endl;
    
    return 0;
}

【运行结果】

3
1 2 3
2
posted @ 2026-01-19 17:20  热爱编程的通信人  阅读(0)  评论(0)    收藏  举报