ABC384题解
[ABC384C] Perfect Standings
题面翻译
Takahashi 决定举办一次编程竞赛。
竞赛包含五道题目:A、B、C、D、E,得分分别为
共有
更具体地说,对于字符串 ABCDE
的每个非空子序列(不一定连续),都有一个以该子序列命名的参赛者,他解答了与其名字中字母对应的题目,而没有解答其他题目。
例如,参赛者 A 只解答了题目 A,参赛者 BCE 解答了题目 B、C 和 E。
输入格式
输出格式
按得分从大到小的顺序打印参赛者的姓名。参与者获得的分数是他们所解决问题的分数的总和。
如果两个参与者获得的分数相同,则首先打印名字在字典中较小的参与者。
制約
- 入力はすべて整数
解题思路
//abc384c
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int grade[10], idx = 0;
bool flag[10];
string s1[5] = {"A", "B", "C", "D", "E"};
struct st{
string a;
int val;
}c[50];
bool cmp(st x, st y){
if(x.val == y.val) return x.a < y.a;
else return x.val > y.val;
}
//递归函数包括,当前枚举到第几个字母,当前枚举构成的字符串,当前构成字符串的值
void f(int alpha, string s, int val){
for(int i = alpha; i < 5; i++){
string temp = s + s1[i];
int v = val + grade[i];
c[++idx].val = v;
c[idx].a = temp;
f(i+1, temp, v);
}
}
int main(){
for(int i = 0; i < 5; i++) cin >> grade[i];
//创造序列
f(0, "", 0);
sort(c+1, c+idx+1, cmp);
for(int i = 1; i <= idx; i++) cout << c[i].a << endl;
return 0;
}
[ABC384D] Repeated Sequence
题面翻译
给定常数
求是否存在两个正整数
制約
- 入力はすべて整数
解题思路
无穷项数列
满足条件的情况可以简化为:
原序列中的部分序列加上
其中,部分序列有两种情况。
- 中间连续的一段
- 开头一段加上结尾一段
因此,可以先让
对于这两种情况,可以通过开两倍空间,重复原序列,生成新一段的前缀和,合并成一种情况
利用双指针枚举 ,一旦序列中有一段满足要求即输出结果,时间复杂度为
//abc384d
#include<stdio.h>
#include<iostream>
using namespace std;
const int N = 400010;
typedef long long ll;
ll a[N], sum1[N], sum2[N];
int main(){
ll n, s;
cin >> n >> s;
for(ll i = 1; i <= n; i++){
cin >> a[i];
sum1[i] = sum1[i-1] + a[i];
}
s = s % sum1[n];
//前缀和开两倍大,处理后一段的值
for(ll i = 1; i <= n; i++) sum1[n+i] = sum1[n] + sum1[i];
//由中间连续的一段构成(双指针判断)
ll l = 1, r = 2;
while(r <= 2 * n){
while(r <= 2 * n && sum1[r] - sum1[l-1] < s) r++;
if(sum1[r] - sum1[l-1] == s && l != r){
cout << "Yes" << endl;
return 0;
}
l++;
}
cout << "No" << endl;
return 0;
}
[ABC384E] Takahashi is Slime 2
题面翻译
有一个网格,水平行数为
最初,单元格
在执行以下任意次数(可能是零次)操作后,找出 Takahashi 的最大可能强度:
- 在与他相邻的史莱姆中,选择一个强度严格小于他强度的
倍的史莱姆并吸收它。结果,被吸收的史莱姆消失,而高桥的实力则增加了吸收史莱姆的实力。
执行上述动作时,消失的史莱姆留下的空隙会立即被高桥填补,消失的史莱姆之前相邻的史莱姆(如果有的话)将与高桥重新相邻。
制約
- 入力はすべて整数
解题思路
可以发现,史莱姆的实力一定是越来越强。如果要满足
同时,
具体代码实现为:
- 建立结构体存储点的横纵坐标以及该点强度值;
- 利用优先队列存储能走到的点,小根堆存储能够保证每次队头元素都是强度值最小的;
- 从起点开始进行bfs扩散,直到所有能够扩散的点都遍历,程序结束。
//abc384e
#include<stdio.h>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
ll a[505][505];
ll ans = 0;
bool flag[505][505];
struct slime{
int x, y;
ll val;
bool operator < (const slime& a) const{
return val > a.val;
}
}s[250010];
//小顶堆
priority_queue<slime> q;
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int h, w, t, x, y;
void bfs(){
while(!q.empty()){
slime temp = q.top();
q.pop();
if(a[temp.x][temp.y] < (ans % t? ans / t + 1: ans / t) || (temp.x == x && temp.y == y)){
ans += a[temp.x][temp.y];
for(int i = 0; i < 4; i++){
int xx = temp.x + dx[i];
int yy = temp.y + dy[i];
if(1 <= xx && xx <= h && 1 <= yy && yy <= w && !flag[xx][yy]){
q.push({xx, yy, a[xx][yy]});
flag[xx][yy] = 1;
}
}
}
}
}
int main(){
cin >> h >> w >> t;
cin >> x >> y;
for(int i = 1; i <= h; i++)
for(int j = 1; j <= w; j++)
cin >> a[i][j];
q.push({x, y, a[x][y]});
flag[x][y] = 1;
bfs();
cout << ans << endl;
return 0;
}
[ABC384F] Double Sum 2
题面翻译
定义 x&(-x)
求得。
现给定一个长度为
制約
- 入力は全て整数
解题思路
如果暴力解决,时间复杂度为
分析可得到
- 当
时,
先处理出来所有元素的
对于序列中元素
其中
- 当
时,需要找到 值。
从
需要用到trie树or桶实现该部分问题。
最后把两部分处理的结果加起来即为答案。
本文作者:hsy2093
本文链接:https://www.cnblogs.com/hsy2093/p/18697455
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步