非官方全题解|欢乐赛#49
2025-06-08 22:18:44
发布于:北京
😊 感谢出题人你好精心准备的题目!废话不多说,让我们开始吧~
1. 除法 🍳
题目描述
给定正整数n,输出n除以2后向上取整的结果
解题思路
使用数学公式(n + 1) / 2实现高效计算:
当n为奇数时,如5→(5+1)/2=3
当n为偶数时,如12→(12+1)/2=6(实际等于6.5但整数除法取整为6)
该方法避免了条件判断,直接计算得到向上取整结果
代码实现
#include <iostream>
using namespace std;
int main() {
    int n;
    cin >> n;
    // 使用向上取整公式:(n+1)/2
    cout << (n + 1) / 2 << endl;
    return 0;
}
2. 买凤梨 🍍
题目描述
有R元钱买菠萝,每个菠萝有美味度k和价格p,求最大美味值总和
解题思路
预处理优化:对每种价格只保留最大美味度的菠萝
枚举计算:遍历1~100的价格区间
公式应用:美味值总和 = 最大美味度 × ⌊R/p⌋
时间复杂度O(100),高效解决数据规模10⁶
代码实现
#include <iostream>
using namespace std;
int main() {
    ios::sync_with_stdio(false); // IO优化
    int n, R;
    cin >> n >> R;
    int best[101] = {0}; // 价格索引数组
    
    // 记录每种价格的最高美味度
    for (int i = 0; i < n; i++) {
        int k, p;
        cin >> k >> p;
        if (k > best[p]) best[p] = k;
    }
    
    long long max_total = 0;
    // 计算每种菠萝的最大美味值
    for (int p = 1; p <= 100; p++) {
        if (p > R) continue; // 跳过超出预算的价格
        long long total = (long long)best[p] * (R / p);
        if (total > max_total) max_total = total;
    }
    cout << max_total << endl;
    return 0;
}
3. 去重 🚫
题目描述
按输入顺序输出第一次出现的数字
解题思路
哈希标记:使用布尔数组记录数字首次出现
顺序扫描:遍历时遇到未标记数字立即输出
格式控制:动态管理空格分隔符
时间复杂度O(n),空间复杂度O(10⁶),完美匹配数据规模
代码实现
#include <iostream>
#include <vector>
using namespace std;
const int MAX_NUM = 1000001; // 10⁶+1
int main() {
    int n;
    cin >> n;
    vector<int> arr(n);
    vector<bool> visited(MAX_NUM, false); // 标记数组
    
    for (int i = 0; i < n; i++) 
        cin >> arr[i];
    
    // 遍历输出首次出现的数字
    bool first = true;
    for (int num : arr) {
        if (!visited[num]) {
            visited[num] = true; // 标记已出现
            if (!first) cout << " ";
            cout << num;
            first = false;
        }
    }
    return 0;
}
4. 幸运数 🍀
题目描述
在区间[x,x+m]中是否存在数位和是t倍数的数?统计幸运数数量
解题思路
预处理优化:提前计算1~n+m所有数的数位和
滑动窗口:维护窗口[x,x+m]中满足条件的计数
动态更新:移动窗口时增删端点计数
时间复杂度O(n+m),避免暴力检查节省时间
代码实现
#include <iostream>
using namespace std;
const int MAX = 100010 + 105; // n+m的最大值
int digitSum[MAX];
bool valid[MAX]; // 标记数位和是t的倍数
int main() {
    int n, m, t;
    cin >> n >> m >> t;
    
    // 预处理数位和
    for (int i = 1; i <= n+m; i++) {
        int sum = 0, num = i;
        while (num) {
            sum += num % 10;
            num /= 10;
        }
        valid[i] = (sum % t == 0);
    }
    
    // 初始化滑动窗口[1, m+1]
    int count = 0;
    for (int i = 1; i <= m+1; i++) 
        if (valid[i]) count++;
    
    // 滑动窗口判断幸运数
    int ans = 0;
    for (int x = 1; x <= n; x++) {
        if (count > 0) ans++; // 存在符合条件的数
        if (valid[x]) count--; // 移除左边界
        if (x+m+1 <= n+m && valid[x+m+1]) 
            count++; // 加入右边界
    }
    
    cout << ans << endl;
    return 0;
}
5. 菠萝排名 🥇
题目描述
筛选出甜度≥a且酸度≤b的菠萝,排序输出编号
解题思路
条件筛选:选择符合阈值条件的菠萝
三级排序:
主排序:甜度降序(高甜度在前)
次排序:酸度升序(低酸度在前)
终排序:编号升序(小编号在前)
稳定排序:使用lambda表达式确保排序稳定性
代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Pineapple { int id, x, y; };
int main() {
    int n, a, b;
    scanf("%d%d%d", &n, &a, &b);
    vector<Pineapple> vec;
    
    // 筛选符合条件的菠萝
    for (int id = 1; id <= n; id++) {
        int x, y;
        scanf("%d%d", &x, &y);
        if (x >= a && y <= b)
            vec.push_back({id, x, y});
    }
    
    // 三级排序
    sort(vec.begin(), vec.end(), [](auto& a, auto& b) {
        if (a.x != b.x) return a.x > b.x; // 甜度降序
        if (a.y != b.y) return a.y < b.y; // 酸度升序
        return a.id < b.id;               // 编号升序
    });
    
    // 输出排名结果
    for (int i = 0; i < vec.size(); i++) {
        if (i) printf(" ");
        printf("%d", vec[i].id);
    }
    return 0;
}
6. 矩阵旋转 🌀
题目描述
将矩阵最外层元素顺时针旋转90度
解题思路
元素提取:按上→右→下→左顺序提取外圈元素
循环移位:整体右移n-1位实现90°旋转
原位放回:按原顺序放回旋转后的元素
内层元素保持不变,仅处理外圈,节省计算资源
代码实现
#include <iostream>
#include <vector>
using namespace std;
int main() {
    int n;
    scanf("%d", &n);
    vector<vector<int>> mat(n, vector<int>(n));
    
    // 读取矩阵
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            scanf("%d", &mat[i][j]);
    
    if (n == 1) {
        printf("%d\n", mat[0][0]);
        return 0;
    }
    
    // 提取外圈元素
    int cnt = 4*(n-1); // 外圈元素总数
    vector<int> temp(cnt), rotated(cnt);
    int idx = 0;
    
    for (int j = 0; j < n; j++) temp[idx++] = mat[0][j];        // 上边
    for (int i = 1; i < n-1; i++) temp[idx++] = mat[i][n-1];   // 右边
    for (int j = n-1; j >= 0; j--) temp[idx++] = mat[n-1][j]; // 下边
    for (int i = n-2; i >= 1; i--) temp[idx++] = mat[i][0];    // 左边
    
    // 循环右移n-1位(等价90°旋转)
    for (int i = 0; i < cnt; i++)
        rotated[(i + n - 1) % cnt] = temp[i];
    
    // 放回旋转后元素
    idx = 0;
    for (int j = 0; j < n; j++) mat[0][j] = rotated[idx++];      // 上边
    for (int i = 1; i < n-1; i++) mat[i][n-1] = rotated[idx++]; // 右边
    for (int j = n-1; j >= 0; j--) mat[n-1][j] = rotated[idx++]; // 下边
    for (int i = n-2; i >= 1; i--) mat[i][0] = rotated[idx++];   // 左边
    
    // 输出结果
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (j) printf(" ");
            printf("%d", mat[i][j]);
        }
        printf("\n");
    }
    return 0;
}
🎉 刷题完毕!大家明白了吗?
如果对任何题解有疑问,欢迎在评论区留言交流~
(所有代码都经过严格测试,确保正确性!)
💡 提示:每个解法都针对题目特点进行优化
🚀 代码均满足时间和空间复杂度要求
👍 原创题解不易,欢迎点赞支持!
PS:@AC君 写题解不容易,给个周边吧!求求了!
这里空空如也













有帮助,赞一个