洛谷 [语言月赛 202503] 题解(C++)

发布于:2025-03-20 ⋅ 阅读:(26) ⋅ 点赞:(0)

本文为洛谷3月的语言月赛题目全部题解,难度为入门到普及-, 觉的有帮助或者写的不错的可以点个赞

题目链接为
题目列表 - 洛谷 | 计算机科学教育新生态

目录

题目A:长方形

解题思路:

代码(C++):

题目B:水流

题目大意:

解题思路:

代码(C++):

题目C:格式转换器

题目大意:

代码(C++):

题目D:环形游走

题目大意:

解题思路:

代码(C++):

题目E:

题目大意:

解题思路:

代码(C++):

题目F:数字棋盘

题目大意:

解题思路:

代码(C++):

题目G:洗牌

题目大意:

解题思路:

代码(C++):

题目H:模拟 + 自定义排序

题目大意:

解题思路:

代码(C++):


题目A:长方形

B4243 [语言月 赛 202503] 长方形 - 洛谷

解题思路:

根据题目意思先算出宽B,然后算出周长L即可

代码(C++):

#include <bits/stdc++.h>

int main() {
    int a, S;
    std::cin >> a >> S;

    int b = S / a;
    int L = 2 * (a + b);

    std::cout << L;
}

题目B:水流

B4244 [语言月赛 202503] 水流 - 洛谷

题目大意:

中间有一个隔板,左右都是水,左边水面高a,右边的水面高b,现在把挡板的高度降低到c,

请问水会向哪个方向移动?或者不移动

解题思路:

关键点:水面存在差别并且挡板高度小于高的那一个水面的时候,水会从高处移到低处

具体可以看代码的判断

代码(C++):

#include <bits/stdc++.h>

int main() {
    int a, b, c;
    std::cin >> a >> b >> c;

    if (a > b && c < a) {
        std::cout << "LeftToRight";
    } else if (a < b && c < b) {
        std::cout << "RightToLeft";
    } else {
        std::cout << "None";
    }
}

题目C:格式转换器

B4245 [语言月赛 202503] 格式转换器 - 洛谷

题目大意:

输入一行排数字,然后用逗号隔开然后输出

不是最后一个数字就输出逗号即可

代码(C++):

#include <bits/stdc++.h>

int main() {
    int n;
    std::cin >> n;

    for (int i = 0; i < n; i++) {
        int a;
        std::cin >> a;
        std::cout << a;
        if (i != n - 1) {
            std::cout << ",";
        }
    }
}

题目D:环形游走

B4246 [语言月赛 202503] 环形游走 - 洛谷

题目大意:

给出一个长度为n的环形数组,开始在下标0处,然后从逆时针方向走m次,每次走的步数为当前的数组位置的元素大小,问走完m次后,在哪里

解题思路:

模拟就行,定义一个变量pos表示当前位置,然后每次移动,让pos = pos - a[pos]即可

当pos小于0的时候,相当于到达加上n的位置

代码(C++):

#include <bits/stdc++.h>

int main() {
    int n, m;
    std::cin >> n >> m;

    std::vector<int> a(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    int pos = 0;
    while (m--) {
        pos = pos - a[pos];
        while (pos < 0) {
            pos += n;
        }
    }
    std::cout << pos + 1;
}

题目E:

B4247 [语言月赛 202503] 半个哥德巴赫猜想 - 洛谷

题目大意:

定义缪零数为:对于正整数 n,如果存在正整数 m(m≥2)使得 n 是 m2 的倍数,则称 n 是一个缪零数

现在给出一个正整数n,你需要找出一个质数,一个缪零数,相加为n,请问这一共有多少种方案,在这些方案中缪零数和质数的差(大数减小数)的最小值为多少

解题思路:

写出两个check函数,分别检查数字是否是缪零数和质数,然后枚举数字x从2到n / 2,定义y = n - x,也就是x + y = n

分别检查x和y是否满足题目条件,如果满足就让方案数目增加,更新答案

具体看代码

代码(C++):

#include <bits/stdc++.h>

int main() {
    int n;
    std::cin >> n;

    auto check1 = [](int x) -> bool {
        for (int i = 2; i <= std::sqrt(x); i++) {
            if (x % (i * i) == 0) {
                return true;
            }
        }
        return false;
    };

    auto check2 = [](int x) -> bool {
        for (int i = 2; i <= std::sqrt(x); i++) {
            if (x % i == 0) {
                return false;
            }
        }
        return true;
    };

    int cnt = 0, ans = INT_MAX;
    for (int x = 2; x <= n / 2; x++) {
        int y = n - x;
        if (check1(x) && check2(y) || check1(y) && check2(x)) {
            cnt++;
            ans = std::min(ans, abs(x - y));
        }
    }

    std::cout << cnt << "\n" << ans;
}

题目F:数字棋盘

B4248 [语言月赛 202503] 数字棋盘 - 洛谷

题目大意:

给你一个n * m的矩阵,然后再给你两个数字x, y

你需要找出在这个矩阵中等于x且此处相邻位置有y的个数

相邻位置的定义是上下左右

比如对于如下矩阵:

对于此矩阵x = 1, y = 2的结果为3

解题思路:

按题目条件模拟就行,遍历矩阵,然后找到等于x 的值,然后对于这个位置找上下左右是否有y,注意边界处理即可,具体过程可以参考代码

代码(C++):

#include <bits/stdc++.h>

int main() {
    int n, m;
    std::cin >> n >> m;

    std::vector<std::vector<int>> a(n, std::vector<int> (m));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            std::cin >> a[i][j];
        }
    }

    int x, y;
    std::cin >> x >> y;

    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (a[i][j] == x) {
                if (i < n - 1 && a[i + 1][j] == y) {
                    ans++;
                } else if (i > 0 && a[i - 1][j] == y) {
                    ans++;
                } else if (j < m - 1 && a[i][j + 1] == y) {
                    ans++;
                } else if (j > 0 && a[i][j - 1] == y) {
                    ans++;
                }
            }
        }
    }

    std::cout << ans;
}

题目G:洗牌

B4249 [语言月赛 202503] 洗牌 - 洛谷

题目大意:

给你两个字符串,第一个字符串为牌的名字,用逗号隔开

保证牌的个数为偶数,先把牌分成两堆

第二个字符串是为洗牌方式,L表示从左边牌堆中取一张,R表示从右边牌堆中取一张

洗完牌后,输出奇数号的牌

解题思路:

首先就是我们先要处理给出的由逗号分开的字符串

然后把牌分成两堆,用两个数组储存两堆牌的内容

再然后就是洗牌,用ans数组储存得出来的牌,然后用双指针模拟洗牌

得出最后的结果,输出偶数下标的即可(数组是从0开始)

模拟题,具体看代码

代码(C++):

#include <bits/stdc++.h>

int main() {
    int n;
    std::cin >> n;
    std::string s, t;
    std::cin.ignore();
    std::getline(std::cin, s);
    std::cin >> t;

    std::vector<std::string> a;
    std::string cur = "";
    for (int i = 0; i < s.size(); i++) {
        if (s[i] == ',') {
            a.push_back(cur);
            cur = "";
        } else {
            cur += s[i];
        }
    }
    a.push_back(cur);


    std::vector<std::string> l, r, ans;
    for (int i = 0; i < 2 * n; i++) {
        if (i < n) {
            l.push_back(a[i]);
        } else {
            r.push_back(a[i]);
        }
    }
    

    int i = 0, j = 0;
    for (char& c : t) {
        if (c == 'L') {
            ans.push_back(l[i]);
            i++;
        } else {
            ans.push_back(r[j]);
            j++;
        }
    }
    
    std::reverse(ans.begin(), ans.end());

    for (int i = 0; i < ans.size(); i++) {
        if (i % 2 == 0) {
            std::cout << ans[i] << "\n";
        }
    }

}

题目H:模拟 + 自定义排序

B4250 [语言月赛 202503] 蛋挞制作工坊 - 洛谷

题目大意:

制作一个蛋挞需要m种材料,每一种材料需要gi数量

现在有n个孩子,分别带了每个材料

然后每个孩子都根据自己的材料数量制作尽可能多数量的蛋挞

然后都混合在一起发放给孩子,根据以下规则发放给孩子:

问题是指定材料为1..2..3到m的时候,分别的分发顺序为多少

解题思路:

首先的问题,就是尽可能多的数量的蛋挞,如何求出每个孩子生产的蛋挞数量呢?

既然每个蛋挞都需要每种材料,确定的数量才能制作,那么可以

对于每种材料,用孩子有的材料 / 需要的材料,取最小值,即为可以这个孩子生产的数量cnt

然后的问题,就是每个孩子每个材料剩下的量,可以用原来的材料的量减去需要的量 / cnt

最后就是自定义排序的环节,根据题目意思写自定义排序即可

为了方便计算和存储,可以用结构体

模拟题,具体写法看代码

代码(C++):

#include <bits/stdc++.h>

struct T{
    int count;
    std::vector<int> left;
    int index;
};

int main() {
    int n, m;
    std::cin >> n >> m;

    std::vector<T> a(n);

    std::vector<int> g(m);
    for (int i = 0; i < m; i++) {
        std::cin >> g[i];
    }

    for (int i = 0; i < n; i++) {
        int cnt = INT_MAX;
        std::vector<int> cur(m);
        for (int j = 0; j < m; j++) {
            int v;
            std::cin >> v;
            cur[j] = v;
            cnt = std::min(cnt, v / g[j]);
        }

        a[i].index = i + 1;
        a[i].count = cnt;

        for (int j = 0; j < m; j++) {
            cur[j] = cur[j] - g[j] * cnt;
        }
        a[i].left = cur;
    }

    for (int i = 0; i < m; i++) {
        std::sort(a.begin(), a.end(), [&](auto u, auto v) {
            if (u.left[i] == v.left[i]) {
                if (u.count == v.count) {
                    return u.index < v.index;
                }
                return u.count > v.count;
            }
            return u.left[i] < v.left[i];
        });

        for (auto& x : a) {
            std::cout << x.index << " ";
        }
        std::cout << "\n";
    }

}