AtCoder Beginner Contest 368


A - Cut#

题意#

签到题

思路#

代码#

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

void solve()
{
    int n, k;
    scanf("%d%d", &n, &k);
    vector<int> v(n);
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &v[i]);
    }
    for (int i = n - k; i < n; i++)
    {
        printf("%d ", v[i]);
    }
    for (int i = 0; i < n - k; i++)
    {
        printf("%d ", v[i]);
    }
}

int main()
{
    int T = 1;
    // scanf("%d", &T);
    while (T--)
    {
        solve();
    }

    return 0;
}


B - Decrease 2 max elements#

题意#

签到题

思路#

数据很小,直接模拟。
其实是一个很经典的贪心算法,算的就是每次任意选两个正数减 1,最多能减多少次,而这个问题的答案就是min(sum / 2, sum - maxn)。

代码一#

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

const int mxn = 1e6 + 5;


void solve()
{
	int n;
	scanf("%d", &n);
	vector<int> v(n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &v[i]);
	}
	int ans = 0;
	while (true)
	{
		sort(v.begin(), v.end(), greater<int>());
		if (v[1] <= 0)
		{
			break;
		}
		v[0]--;
		v[1]--;
		ans++;
	}
	printf("%d", ans);
}


int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int T = 1;
	//scanf("%d", &T);
	while (T--)
	{
		solve();
	}

	return 0;
}

代码二#

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

const int mxn = 1e6 + 5;


void solve()
{
	int n, sum = 0, maxn = -1;
	scanf("%d", &n);
	vector<int> v(n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &v[i]);
        sum += v[i];
        maxn = max(maxn, v[i]);
	}
	
	printf("%d", min(sum / 2, sum - maxn));
}


int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int T = 1;
	//scanf("%d", &T);
	while (T--)
	{
		solve();
	}

	return 0;
}

C - Triple Attack#

题意#

n个人,第i个人的血量是h_i,t从0开始计数,每次操作t++,t是3的倍数扣3点血,否则扣1点血。求使所有人血量<=0的操作数。

思路#

每3次为一循环,每轮循环扣5点血,超出一次循环的部分可以直接计算,剩下的至多模拟2次即可。

代码#

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long

const int mxn = 1e6 + 5;

void solve()
{
	int n;
	scanf("%lld", &n);
	vector<int> v(n);
	for (int i = 0; i < n; i++)
	{
		scanf("%lld", &v[i]);
	}
	int ans = 0;
	for (int i = 0; i < n; i++)
	{
		ans += v[i] / 5 * 3;
		v[i] %= 5;
		while (v[i] > 0)
		{
			ans++;
			v[i] -= (ans % 3 ? 1 : 3);
		}
	}
	printf("%lld", ans);
}


signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int T = 1;
	//scanf("%lld", &T);
	while (T--)
	{
		solve();
	}

	return 0;
}

D - Minimum Steiner Tree#

题意#

给定一棵n条边的树,以及k个点,删点删边使得剩下的点中包含所给的k个点,问剩下结点数的最小值。

思路#

从一个要保留的点出发,以各最终要保留点为根分治每颗子树,将各自要保留的点数相加。
(感觉树的题大部分是dfs?🤔

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

const int mxn = 1e6 + 5;

int n, k, idx, ans;
int to[mxn], nxt[mxn], head[mxn];
bool vis[mxn], mark[mxn]; // 要留下的点

void add(int u, int v)
{
	to[++idx] = v;
	nxt[idx] = head[u];
	head[u] = idx;
}

int dfs(int u)
{
	vis[u] = true;
	int cnt = 0; // 以u为根的子树要保留的节点数
	for (int i = head[u]; i; i = nxt[i]) // 遍历邻点
	{
		int v = to[i];
		if (!vis[v])
		{
			cnt += dfs(v);
		}
	}
	if (cnt || mark[u]) // cnt > 0 表示该结点需要保留(一定会经过它)
	{
		cnt++;
	}
	return cnt;
}

int main()
{
	scanf("%d%d", &n, &k);
	for (int i = 1; i < n; i++)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		add(u, v);
		add(v, u);
	}
	int st;
	for (int i = 0; i < k; i++)
	{
		int x;
		scanf("%d", &x);
		mark[x] = true;
		st = x; // 选一个要保留的点为起点
	}
	printf("%d", dfs(st));
}

F - Dividing Game#

题意#

给定n个整数,Anna先手Bruno后手轮流操作,选一个数将它变为自己的因子(不能是本身),最先不能操作的一方输。两人以最佳方式下棋,问谁能赢。

思路#

公平组合游戏,而且总状态有限,容易想到sg函数。

代码#

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>

using namespace std;

const int mxn = 1e6 + 5;

int v[mxn], f[mxn];

int sg(int x)
{
	if (f[x] != -1)
	{
		return f[x];
	}
	set<int> s;
	for (int i = 1; i <= sqrt(x); i++)
	{
		if (x % i)
		{
			continue;
		}
		// 两个因子
		if (i != 1)
		{
			s.insert(sg(x / i));
		}
		if (i != x)
		{
			s.insert(sg(i));
		}
	}
	//mex
	for (int i = 0; ; i++)
	{
		if (!s.count(i))
		{
			return f[x] = i;
		}
	}
}

int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &v[i]);
	}
	int res = 0;
	fill(f, f + mxn, -1);
	for (int i = 1; i <= n; i++)
	{
		res ^= sg(v[i]);
	}
	if (res)
	{
		printf("Anna");
	}
	else
	{
		printf("Bruno");
	}
	return 0;
}

比赛链接 https://atcoder.jp/contests/abc368

posted @   _SeiI  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示