当前位置: 首页 > article >正文

AtCoder Beginner Contest 368 题ABCD详细题解(C++,Python)

前言:        

        第一次参加atc的比赛,总体来说比codeforces好,至少不会in queue我也尝试了一下用go写,体验还不错,这个beginner感觉跟cf的div3难度差不多,思维难度不高,感觉主要考察基础的编码能力。这次比赛E难度不合理,E通过的数量比G还少

        本文为此比赛题ABCDF的详细题解,包含C++,Python语言描述,如果觉得有帮助或者写的不错可以点个赞,之后我会更新cf, atc, 洛谷比赛的某些题目题解(本人能力不够无法AK只能写某些题目的题解了,之后能力够了会写的)

比赛题目链接:

Tasks - Hitachi Vantara Programming Contest 2024(AtCoder Beginner Contest 368)

目录

题A:

题目大意和思路:

代码(C++):

代码(Python):

题B:

题目大意和思路:

代码(C++):

代码(Python):

题C:

题目大意和思路:

代码(C++):

代码(Python):

题D:

题目大意和思路:

代码(C++):


题A:

A - Cut (atcoder.jp)

题目大意和思路:

有一堆N张卡片,从顶部数起第i张卡片上写着整数Ai。

你从底部取出K张卡片,并将它们按原来的顺序放到堆顶。

请按从上到下的顺序输出操作后卡片上的整数

输入:

5 3
1 2 3 4 5

输出:

3 4 5 1 2

就是把数组后面k个数字放在前面,直接输出就可以了,先输出数组后面k,再输出前面的n - k个

代码(C++):

int main() {
    int n, k;
    std::cin >> n >> k;
    std::vector<int> a(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    for (int i = n - k; i < n; i++) {
        std::cout << a[i] << " ";
    }
    for (int i = 0; i < n - k; i++) {
        std::cout << a[i] << " ";
    }
    std::cout << std::endl;
}

代码(Python):

def main():
    n, k = map(int, input().split())
    arr = list(map(int, input().split()))
    print(*arr[n - k:], *arr[:n - k], end = " ")

题B:

B - Decrease 2 max elements (atcoder.jp)

题目大意和思路:

一个正整数数组,进行下面操作:

降序排列,然后前两个元素减一

问需要多少次才能使得数组只剩下一个或者0个元素

数据量不大,可以直接暴力模拟做,每次排序后,当最大的数字小于等于0的时候,也就输无法再减的时候退出循环即可

暴力模拟代码:

int main() {
	int n;
	std::cin >> n;
	std::vector<int> a(n);
	for (int i = 0; i < n; i++) {
		std::cin >> a[i];
	}
	int res = 0;
	while (1) {
		std::sort(a.begin(), a.end());
		if (a[n - 2] <= 0) {
			break;
		}
		a[n - 1]--;
		a[n - 2]--;
		res++;
	}
	std::cout << res << std::endl;
}

但是有个更好的思路,(当时比赛想了一会,看到数据不大就暴力模拟了),参考jiangly的代码(前排貌似就他用的不是暴力模拟)

题目的意思就是,每次操作将数组中最大的两个数字减一,要使整个数组只剩一个或零个正整数

那么关注剩下的那个数字即可

有两种情况,第一种是保留的数字为第二小的数字,第二种是保留的数字是最大的数字,一种是数字大小比较接近,操作次数就是数字的和除以2,一种就是最大值保存到最后,此时最大值满足大于sum的一半即可

代码(C++):

int main() {
	int n;
	std::cin >> n;
	int mx = 0, sum = 0;
	for (int i = 0; i < n; i++) {
		int x;
		std::cin >> x;
		sum += x;
		mx = std::max(x, mx);
	}
	int res = std::min(sum / 2, sum - mx);
	std::cout << res << std::endl;
}

代码(Python):

def main():
    n = int(input())
    arr = list(map(int, input().split()))
    sum_val = sum(arr)
    mx = max(arr)
    res = min(sum_val // 2, sum_val - mx)
    print(res)

题C:

C - Triple Attack (atcoder.jp)

题目大意和思路:

这题可以这么理解

就是一些怪,从前往后攻击,第一刀伤害1,第二刀伤害1,第三刀伤害3

然后问需要多少刀可以全部杀完

这个数据量肯定不能用暴力做的

3刀一循环,总共会造成5伤害

那么对于每一个元素,可以对5进行取余然后关注余数的就可以了

然后关注当前是哪一刀,再对这个元素剩余的进行“砍”就可以了

注意数据,要用long long

代码(C++):

int main() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }
    long long t = 0;
    for (auto& x : a) {
        int c = x / 5;
        t += c * 3;
        x -= c * 5;
        //当此时这个怪还有剩余的血量后
        //此时t++,然后看此时是哪一刀对x剩余进行减即可
        while (x > 0) {
            t++;
            if (t % 3 == 0) {
                x -= 3;
            } else {
                x -= 1;
            }
        }
    }
    std::cout << t << std::endl;
}

代码(Python):

def main():
    n = int(input())
    a = list(map(int, input().split()))
    t = 0
    for x in a:
        c = x // 5
        t += c * 3
        x -= c * 5
        while x > 0:
            t += 1
            if t % 3 == 0:
                x -= 3
            else:
                x -= 1
    print(t)

题D:

D - Minimum Steiner Tree (atcoder.jp)

题目大意和思路:

就是给你一个树,然后再给你k个点,让你求这个树中包含这k个点的最小节点数

板子题,贴个板子(其实我也不算太理解)

代码(C++):

#include <iostream>
#include <vector>

std::vector<std::vector<int>> adj;
std::vector<int> f, sum;
int n, k;

int res = 0;
void dfs(int x, int p) {
    sum[x] = f[x];
    int cnt = (f[x] == 1) ? 2 : 0;
    for (int y : adj[x]) {
        if (y == p) continue;
        dfs(y, x);
        sum[x] += sum[y];
        if (sum[y] > 0) cnt++;
    }
    if (sum[x] < k) cnt++;
    if (cnt >= 2) res++;
}

int main() {
    std::cin >> n >> k;
    adj.resize(n);
    for (int i = 0; i < n - 1; i++) {
        int x, y;
        std::cin >> x >> y;
        x--; y--;
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    f.resize(n, 0);
    for (int i = 0; i < k; i++) {
        int v;
        std::cin >> v;
        v--;
        f[v] = 1;
    }
    sum.resize(n, 0);
    dfs(0, -1);
    std::cout << res << std::endl;
    return 0;
}


http://www.kler.cn/a/280561.html

相关文章:

  • Python测试框架之—— pytest介绍与示例
  • Linux--NAT,代理服务,内网穿透
  • 谷歌chrome浏览器显示“版本太旧”又无法更新情况下,如何关闭“Chrome版本太旧”提示,包括直接启动Google浏览器,或者通过其他应用启动
  • 【焕新】同为科技(TOWE)23周年庆典
  • Python中的if语句:通往逻辑世界的钥匙
  • Yololov5+Pyqt5+Opencv 实时城市积水报警系统
  • 通过写文件方式写入 Hive 数据
  • 进程与程序的学习
  • 计算机毕业设计选题推荐-OA办公管理系统-Java/Python项目实战
  • Docker续5:容器网络
  • Java超市收银系统(十、爬虫)
  • 重构贪心算法(一)
  • 机器学习 之 DBSCAN算法 及实现
  • linux samba 安装与配置说明
  • YOLOv8改进 | 模块融合 | C2f融合 ghost + DynamicConv 【两次融合 + 独家改进】
  • SQL中NULL值导致NOT IN操作符异常查询的问题
  • 趋动科技联合云轴科技推出GPU云原生超融合解决方案
  • Spring不是引入了三级缓存,解决了循环依赖的问题吗?
  • UE5.4内容示例(5)UI_CommonUI - 学习笔记
  • 如何满足业主多元需求?开发物业APP,打造智能社区生活