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

本文为洛谷 [语言月赛 202410] 的全部题解(最后一题太麻烦暂时给不出完整代码)

目录

题一:

题目大意和解答思路:

代码(C++):

题二:

题目大意和解答思路:

代码(C++):

题三:

题目大意和解答思路:

代码(C++):

题四:

题目大意和解答思路:

代码(C++):

题五:

题目大意和解答思路:

代码(C++):

题六:

题目大意和解答思路:

代码(C++):        

题七:

题目大意和解答思路:

代码(C++):

题八:

题目大意和解答思路:


题一:

B4042 [语言月赛 202410] 顺序结构 - 洛谷 | 计算机科学教育新生态

题目大意和解答思路:

根据题目对输入进来的变量a进行操作即可

代码(C++):

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);

    int a;
    std::cin >> a;
    std::cout << (a + 5) * 3 << " " << a * 3 + 5 << "\n";
}

题二:

题目大意和解答思路:

题目关键:

她想知道有哪些刻度和 a 厘米刻度的距离恰好是 b

比较a - b >= 0, 比较  a + b <= n

满足前者,就输出a - b
满足后者,就输出a + b
都不满足就输出No solution
注意b = 0 的时候,输出a

根据上面思路即可很快完成代码

我这里使用一个vector简化

代码(C++):

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    
    int n, a, b;
    std::cin >> n >> a >> b;
    if (b == 0) {
        std::cout << a << "\n";
        return 0;
    }

    std::vector<int> res;
    if (a - b >= 0) res.push_back(a - b);
    if (a + b <= n) res.push_back(a + b);

    if (res.empty()) {
        std::cout << "No solution\n";
    } else {
        for (int x : res) {
            std::cout << x << " ";
        }
        std::cout << "\n";
    }
}

题三:

B4045 [语言月赛 202410] 同桌 - 洛谷 | 计算机科学教育新生态

题目大意和解答思路:

就是说,现在是第一周的周六

然后每个课程都会在第一次课都会在第一周开始,w为星期几开始,d为隔几周开一次课

求下一次最近上课的需要隔多少天
 

都是周一到周五,所以没有其他的条件

直接算出每个课程下次上课的间隔,然后求出最小值即可

代码(C++):

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);

    int n;
    std::cin >> n;

    int res = 14 * 7; //d 最大为14,所以可以初始化14 * 7
    for (int i = 0; i < n; i++) {
        int w, d;
        std::cin >> w >> d;
        int next = (w - 6) + d * 7;
        res = std::min(res, next);
    }
    std::cout << res << "\n";
}

题四:

B4045 [语言月赛 202410] 同桌 - 洛谷 | 计算机科学教育新生态

题目大意和解答思路:

就是说,一共有n 个桌子,2 * n个人,然后每两个人坐一个桌子,这两个人是同桌

然后输入每个人希望的同桌,判断最后是否能满足每个人的希望,注意自己不能跟自己为同桌

很常规的模拟

首先用一个大小为2*n + 1的数组A来存数据(下标从1开始),然后呢

首先自己不能跟自己做同桌,那么A[i] != i这个条件必须满足

然后判断希望的同桌, 编号A[i] 是编号 第 i 位同学希望的同桌, 那么编号A[i] 希望的同桌呢?很明显是A[A[i]], 那么此时只用判断A[A[i]] == i 这个条件即可

代码(C++):

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);

    int n;
    std::cin >> n;
    std::vector<int> A(n * 2 + 1);
    
    for (int i = 1; i <= 2 * n; i++) {
        std::cin >> A[i];
    }
    for (int i = 1; i <= 2 * n; i++) {
        bool f = (A[i] != i && A[A[i]] == i);
        if (!f) {
            std::cout << "No\n";
            return 0;
        }
    }
    std::cout << "Yes\n";
}

题五:

B4046 [语言月赛 202410] 寻找质数 - 洛谷 | 计算机科学教育新生态

题目大意和解答思路:

题目意思就是,从1 ~ n这n个数字中,满足“孤独数”性质的数字,第k大的是多少

可以这么模拟,先定义一个变量cnt, 从n 开始循环遍历到 1,碰到一个满足条件的“孤独数”就把cnt++,当cnt == k的时候,表示找到了第k大的数字,输出然后return 0 即可

遍历完还没找到的话,输出-1即可

代码(C++):

bool is_prime(int n) {
    if (n <= 1) return false;
    if (n <= 3) return true;
    if (n % 2 == 0 || n % 3 == 0) return false;

    for (int i = 5; i * i <= n; i += 6) {
        if (n % i == 0 || n % (i + 2) == 0) return false;
    }
    return true;
}
bool is_lone(int n, int m, int r) {
    return is_prime(n) && n % m == r;
}
int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);

    int n, m, r, k;
    std::cin >> n >> m >> r >> k;
    int cnt = 0;
    for (int i = n; i >= 1; i--) {
        if (is_lone(i, m, r)) {
            cnt++;
        }
        if (cnt == k) {
            std::cout << i << "\n";
            return 0;
        }
    }
    std::cout << "-1\n";
}

题六:

B4047 [语言月赛 202410] 校门外的施工 - 洛谷 | 计算机科学教育新生态

题目大意和解答思路:

这题主要是要读清楚题目的意思,一共有m棵树,每个树之间有一片绿化带

然后进行了n次施工,施工类型为两种,然后题目是求施工后还剩下多少棵树

这题就是源于题目的改编:P1047 [NOIP2005 普及组] 校门外的树 - 洛谷 | 计算机科学教育新生态

加了一个绿化带然后和施工方案

数据量不大,重复遍历即可

首先根据题目条件就是一个长度为2 * m的全部元素初始化为1数组(下标从1开始),然后每一棵树的位置x变成了x * 2 - 1

然后每次施工,根据条件,把这一区间都变成0,最后数出树的个数和绿化带个数即可

当然还有效率更高的方法,可以参考我的文章,区间合并:

算法题练习小技巧之区间合并--套路详细讲解带例题和源码(Python,C++)_区间合并c++-优快云博客

代码(C++):        

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);

    int m, n;
    std::cin >> m >> n;
    std::vector<int> A(2 * m, 1);
    while (n--) {
        int op, l, r;
        std::cin >> op >> l >> r;
        if (op == 1) {
            for (int i = 2 * l; i < r * 2 - 1; i++) {
                A[i] = 0;
            }
        } else {
            for (int i = 2 * l - 1; i <= r * 2 - 1; i++) {
                A[i] = 0;
            }
        }
    }
    int cnt1 = 0, cnt2 = 0;
    for (int i = 1; i < 2 * m; i++) {
        if (A[i]) {
            if (i % 2 == 0) {
                cnt2++;
            } else {
                cnt1++;
            }
        }
    }
    std::cout << cnt1 << " " << cnt2 << "\n";
}

题七:

B4048 [语言月赛 202410] 断章取义 - 洛谷 | 计算机科学教育新生态

题目大意和解答思路:

有点看不懂这个题目的T是啥意思

题目的意思就是说,给一个字符串,让你每一轮删除里面所有的"not"
让你输出最后的字符串和删除轮数

库函数秒了,先用一个while 1循环,然后 .find("not"),找出第一个not的位置,如果没找到就退出大循环,如果找到了,就从这个位置开始反复找和删,然后cnt++即可


代码(C++):

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);

    int t;
    std::cin >> t;
    std::string s;
    std::cin >> s;

    int cnt = 0;
    while (true) {
        int idx = s.find("not");
        if (idx == std::string::npos) {
            break;
        }
        while (idx != std::string::npos) {
            s.erase(idx, 3);
            idx = s.find("not", idx);
        }
        cnt++;
    }
    std::cout << s << "\n" << cnt << "\n";
}

题八:

B4049 [语言月赛 202410] 平均分计算 - 洛谷 | 计算机科学教育新生态

题目大意和解答思路:

感觉好麻烦, 而且学号还放在最后一位了,真恶心

不过可以用结构体进行模拟吧
 

struct Course {
    int people;
    std::vector<int> id;
    std::vector<int> part;
    std::vector<int> score;

    Course(int p) : people(p), id(p), part(p), score(p) {}
};

然后最后记得用gcd方法来格式化答案

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值