Atcoder Beginner Contest 271
前言#
一场掉分的 ABC /kk
在花了 分钟看完前 题后,选择了赛场上大部分人使用的:先开 D,再按顺序做 A、B、C。(打题的时候才发现应该先开 C 的 QwQ)
但却因为 CSP-S 神秘的太空射线使得自身膨胀,结果 E 想复杂 ,当场去世。
都是因为 CSP-S,不是我的错
ABC 271 A 题#
题目大意:
你需要把 转换成一个两位的 进制数,若不足两位则加上前导 。
解法分析:
此题考查人们对输出语句的熟悉程度。
题目解法不多说,直接上代码。
AC Code:
# include <bits/stdc++.h>
using namespace std;
# define ll long long
# define lf double
# define GO(i,a,b) for(ll i = a; i <= b; i ++)
# define RO(i,b,a) for(ll i = b; i >= a; i --)
# define FO(i,u,head,e) for(int i = head[u]; i; i = e[i].next)
# define CI const int
# define pii pair<int,int>
# define MP(a,b) make_pair(a, b)
# define PB(x) push_back(x)
# define mem(a,x) memset(a, x, sizeof a)
# define F first
# define S second
int n;
int main(){
scanf("%d", &n);
printf("%02llX", n);
return 0;
}
ABC 271 B 题#
题目大意:
给你 个数组,第 个数组大小为 ,再有 次询问,每次问你第 个数组的第 项是什么。
解法分析:
说句闲话,vector 是个好东西。
这道题显然需要动态大小的数组,那就非 vector 莫属了。
AC Code:
# include <bits/stdc++.h>
using namespace std;
# define ll long long
# define lf double
# define GO(i,a,b) for(ll i = a; i <= b; i ++)
# define RO(i,b,a) for(ll i = b; i >= a; i --)
# define FO(i,u,head,e) for(int i = head[u]; i; i = e[i].next)
# define CI const int
# define pii pair<int,int>
# define MP(a,b) make_pair(a, b)
# define PB(x) push_back(x)
# define mem(a,x) memset(a, x, sizeof a)
# define F first
# define S second
CI maxn = 2e5 + 7;
int n, q;
int l;
vector <int> a[maxn];
int x, y;
int main(){
cin >> n >> q;
GO (i, 1, n){
scanf("%d", &l);
GO (j, 1, l){
int p;
scanf("%d", &p);
a[i].push_back(p);
}
}
while (q --){
scanf("%d %d", &x, &y);
printf("%d\n", a[x][y - 1]);
}
return 0;
}
ABC 271 C 题#
题目大意:
高桥有 本书,第 本编号为 。他可以不停的卖 本书获得一本任意编号的书,但当剩下的书不到 本时就不能这样了。现在高桥想要从编号为 的书开始读,看完一本就看下一个编号的书,如果没有就不能看了。高桥想尽量多的看书,请计算高桥最多可以看多少本书。
解法分析:
有两种做法,这里只讲二分。
这道题说到了最多
,就想到了二分。考虑当现在二分到了 ,那么:
- 重复编号的书可以直接卖掉
- 剩下不重复编号但是编号大于 的书也可以卖掉
当你将所有可以买的书卖掉后,看能不能达到期望的数量即可。
AC Code:
# include <bits/stdc++.h>
using namespace std;
# define ll long long
# define lf double
# define GO(i,a,b) for(ll i = a; i <= b; i ++)
# define RO(i,b,a) for(ll i = b; i >= a; i --)
# define FO(i,u,head,e) for(int i = head[u]; i; i = e[i].next)
# define CI const int
# define pii pair<int,int>
# define MP(a,b) make_pair(a, b)
# define PB(x) push_back(x)
# define mem(a,x) memset(a, x, sizeof a)
# define F first
# define S second
CI maxn = 3e5 + 7;
int n, m;
int a[maxn];
bool check(int mid){
int res = 0;
GO (i, 1, m)
res += (a[i] <= mid);
return (mid - res) * 2 <= (n - res);
}
int main(){
cin >> n;
GO (i, 1, n)
scanf("%d", &a[i]);
sort(a + 1, a + n + 1);
m = 1;
GO (i, 2, n)
if (a[i] != a[i - 1])
a[++ m] = a[i];
int l = 0, r = 1e9;
int ans = 0;
while (l <= r){
int mid = (l + r) >> 1;
if (check(mid)){
ans = mid;
l = mid + 1;
}
else r = mid - 1;
}
cout << ans;
return 0;
}
ABC 271 D 题#
题目大意:
一共有 张牌,每一面都写着一个整数。卡 ()前面写着整数 ,后面写着整数 。
你可以选择是否放置每张卡片的正面或背面可见。
确定是否可以调整卡片的正反面,使得可见整数的和恰好等于 ,如果可能的话,找到卡片的位置来实现这一点。
解法分析:
这是一道一眼盯真的题。这道题目长得就像个 DP,那就设 为 前i个数和是否能凑成j
,转移方程就是 。
又说这道题需要输出路径,这就是一个经典的路径还原了。设 为计算 时做出的选择,然后从后往前递归输出即可。
AC Code:
# include <bits/stdc++.h>
using namespace std;
# define ll long long
# define lf double
# define GO(i,a,b) for(ll i = a; i <= b; i ++)
# define RO(i,b,a) for(ll i = b; i >= a; i --)
# define FO(i,u,head,e) for(int i = head[u]; i; i = e[i].next)
# define CI const int
# define pii pair<int,int>
# define MP(a,b) make_pair(a, b)
# define PB(x) push_back(x)
# define mem(a,x) memset(a, x, sizeof a)
# define F first
# define S second
CI maxn = 107;
int n, s;
int a[maxn], b[maxn];
bool f[maxn][10007];
char w[maxn][10007];
void out(int n, int s){
if (n == 0)
return ;
out(n - 1, s - (w[n][s] == 'H' ? a[n] : b[n]));
printf("%c", w[n][s]);
}
int main(){
cin >> n >> s;
GO (i, 1, n)
scanf("%d %d", &a[i], &b[i]);
f[0][0] = true;
GO (i, 1, n){
GO (j, 0, s){
f[i][j] = max <bool> ((j >= a[i] ? f[i - 1][j - a[i]] : 0), (j >= b[i] ? f[i - 1][j - b[i]] : 0));
if (j >= a[i] && f[i][j] == f[i - 1][j - a[i]])
w[i][j] = 'H';
else if (j >= b[i] && f[i][j] == f[i - 1][j - b[i]])
w[i][j] = 'T';
else
w[i][j] = 'I';
}
}
printf(f[n][s] ? "Yes\n" : "No\n");
if (f[n][s]) out(n, s);
return 0;
}
ABC 271 E 题#
题目大意:
有一个有向图, 有 个编号为 的点和 条编号为 的路。
第 条路从 到 ,长度是 。
给定长度为 的序列 ,由 和 之间的整数组成。从城镇 到城镇 的道路被称为好路径,如果:
按照路径中使用的顺序排列的道路编号序列是 的子序列。
找出一条好的路径所使用的道路长度的最小和。
解法分析:
赛场上想复杂了很多次,一直以为要用 Dijsktra 来做,但其实不然。题目中说一定要按照顺序来走(构成子序列),从另一方面来看,这是在帮我们建图。因为我们只能用 中的边,还要按顺序使用,则不会出现编号靠后的边比编号靠前的边先走的情况,这就满足了 DP 的无后效性。而 DP 的另外两个性质也是显而易见的满足,于是这道题思路就出来了:设 为走到 的最短路,则按顺序遍历 的每一条边,每次更新就是 ,最后输出 即可。
AC Code:
# include <bits/stdc++.h>
using namespace std;
# define ll long long
# define lf double
# define GO(i,a,b) for(ll i = a; i <= b; i ++)
# define RO(i,b,a) for(ll i = b; i >= a; i --)
# define FO(i,u,head,e) for(int i = head[u]; i; i = e[i].next)
# define CI const int
# define pii pair<int,int>
# define MP(a,b) make_pair(a, b)
# define PB(x) push_back(x)
# define mem(a,x) memset(a, x, sizeof a)
# define F first
# define S second
CI maxn = 2e5 + 7;
int n, m, k;
int u[maxn], v[maxn], w[maxn];
int a, b;
ll dis[maxn];
int main(){
cin >> n >> m >> k;
GO (i, 1, n)
dis[i] = 2e18;
GO (i, 1, m)
scanf("%d %d %d", &u[i], &v[i], &w[i]);
dis[1] = 0;
GO (i, 1, k){
scanf("%d", &a);
dis[v[a]] = min <ll> (dis[v[a]], dis[u[a]] + w[a]);
}
cout << (dis[n] == 2e18 ? -1 : dis[n]);
return 0;
}
作者:DE_aemmprty
出处:https://www.cnblogs.com/aemmprty/p/16757496.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库