比赛链接

A

题解

知识点:模拟

时间复杂度 \(O(1)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; bool solve() {
int a, b, c;
cin >> a >> b >> c;
int x = a - 1;
int y = abs(b - c) + c - 1;
if (x > y) cout << 2 << '\n';
else if (x < y) cout << 1 << '\n';
else cout << 3 << '\n';
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

B

题解

知识点:模拟。

倒着来,很方便。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; bool solve() {
int n;
cin >> n;
string T;
cin >> T;
string S;
for (int i = T.length() - 1;i >= 0;i--) {
if (T[i] == '0') {
S = (char)((T[i - 1] - '0') + (T[i - 2] - '0') * 10 + 'a' - 1) + S;
i -= 2;
}
else {
S = (char)(T[i] - '0' + 'a' - 1) + S;
}
}
cout << S << '\n';
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

C

题解

知识点:贪心,枚举。

显然最小花费是 \(|s[n]-a[1]|\) ,最大化路线的方式是按序走过 \(s[1]\) 到 \(s[n]\) 的所有字母。

把每个字母的下标放进桶中 , \(s[1]\) 比 \(s[n]\) 小则从 \(s[1]\) 正序,否则从 \(s[1]\) 倒序。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; bool solve() {
string s;
cin >> s;
int n = s.length();
s = "?" + s;
vector<vector<int>> v(26);
for (int i = 1;i <= n;i++) {
v[s[i] - 'a'].push_back(i);
}
int x = s[1] - 'a', y = s[n] - 'a';
if (x < y) {
int cnt = 0;
for (int i = x;i <= y;i++) {
cnt += v[i].size();
}
cout << abs(s[n] - s[1]) << ' ' << cnt << '\n';
for (int i = x;i <= y;i++)
for (auto j : v[i]) cout << j << ' ';
}
else {
int cnt = 0;
for (int i = x;i >= y;i--) {
cnt += v[i].size();
}
cout << abs(s[n] - s[1]) << ' ' << cnt << '\n';
for (int i = x;i >= y;i--)
for (auto j : v[i]) cout << j << ' ';
}
cout << '\n';
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

D

题解

知识点:贪心,枚举,双指针。

处理出 \(y-x\) 得到每个成员的贡献,从小到大排序,最小的和最大的两人一组即可最大化分组数量,不能分配就跳过较小的。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; int diff[100007];
bool solve() {
int n;
cin >> n;
for (int i = 1;i <= n;i++) cin >> diff[i];
for (int i = 1;i <= n;i++) {
int y;
cin >> y;
diff[i] = y - diff[i];
}
sort(diff + 1, diff + n + 1);
int ans = 0;
int l = 1, r = n;
while (l < r) {
if (diff[l] + diff[r] >= 0) ans++, r--;
l++;
}
cout << ans << '\n';
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

E

题解

知识点:贪心。

\(i\) 从 \(2\) 开始依次询问。先询问 \((1,i)\) ,如果结果 \(-1\) 则输出 \(i-1\) ;否则,再询问一次 \((i,1)\) ,如果答案和 \((1,i)\) 不同则输出两个答案之和,否则继续下一个 \(i\) 。除去特判 \(n \in [3,25]\) 会因为询问到 \(-1\) 结束的情况,其他情况只需要一组答案不同即可,概率很高。

时间复杂度 \(O(1)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; ll query(ll a, ll b) {
cout << "? " << a << ' ' << b << endl;
ll ans;
cin >> ans;
return ans;
} void answer(ll x) {
cout << "! " << x << endl;
exit(0);
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
for (int i = 2;i;i++) {
ll ans1 = query(1, i);
if (!~ans1) answer(i - 1);
ll ans2 = query(i, 1);
if (ans1 != ans2) answer(ans1 + ans2);
}
return 0;
}

F

题解

知识点:枚举,前缀和,数论。

注意到一个数字 \(\mod 9\) 的答案和所有数位加起来 \(\mod 9\) 的答案相同,因此先对 \(s\) 数位预处理模意义前缀和。

然后处理出所有 \(w\) 长度的串的余数,把串首坐标放进桶中对应余数的位置,只需要存两个最左边的即可。

对于每组询问,遍历余数 \(a,b\) 满足 \(a \cdot re + b \equiv k \pmod 9\) ,其中 \(re\) 为 \([l,r]\) 的余数。将余数 \(a,b\) 对应的串下标更新一下答案即可,答案可以用 pair 存,方便更新。注意特判 \(a = b\) 的情况,需要同一个余数的前两个下标。

时间复杂度 \(O(n+m)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; int a[200007];
bool solve() {
string s;
cin >> s;
int n = s.length();
s = "?" + s;
for (int i = 1;i <= n;i++) a[i] = (s[i] - '0' + a[i - 1]) % 9;
int w, m;
cin >> w >> m;
vector<vector<int>> pos(9);
for (int i = w;i <= n;i++) {
int re = (a[i] - a[i - w] + 9) % 9;
if (pos[re].size() < 2) pos[re].push_back(i - w + 1);
}
while (m--) {
int l, r, k;
cin >> l >> r >> k;
int re = (a[r] - a[l - 1] + 9) % 9;
pair<int, int> ans = { n + 1,n + 1 };
for (int i = 0;i <= 8;i++) {
if (pos[i].empty()) continue;
for (int j = 0;j <= 8;j++) {
if (pos[j].empty()) continue;
if ((i * re + j) % 9 == k) {
if (i != j) ans = min(ans, { pos[i][0],pos[j][0] });
else if (i == j && pos[i].size() == 2) ans = min(ans, { pos[i][0],pos[i][1] });
}
}
}
if (ans > pair<int, int>{n, n}) cout << -1 << ' ' << -1 << '\n';
else cout << ans.first << ' ' << ans.second << '\n';
}
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

G

题解

知识点:线性dp。

预处理出 \(s\) 中所有能删除 \(t\) 的下标,暴力 \(O(n^2)\) 处理即可,存进 vector 。随后dp一下前 \(i\) 个能删除位置的最小删除次数。

设 \(f[i]\) 为考虑到第 \(i\) 个能删除的位置,删除 \([1,v[i]]\) 所有能删除的段,且一定删除第 \(i\) 段的最小删除次数。设 \(tot[i]\) 为能够达成 \(f[i]\) 删除次数的对应的方案数。

对于 \(v[i]\) ,我们枚举上一个删除的位置 \(v[j]\) ,先保证 \(i,j\) 不重合即 \(v[i]-v[j]\geq m\) ,然后保证 \(i,j\) 中间没有别的能删除的段即 $v[k] - v[j] < m $ 以及 $ v[i] - v[k] < m$ 。于是可以转移:

if (f[i] > f[j] + 1) {
f[i] = f[j] + 1;
tot[i] = tot[j];
}
else if (f[i] == f[j] + 1) {
tot[i] = (tot[i] + tot[j]) % mod;
}

最后统计末尾重合的一段的最小删除次数,以及对应的总方案数。

时间复杂度 \(O(nm^2)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; const int mod = 1e9 + 7; bool solve() {
string s, t;
cin >> s >> t;
int n = s.size(), m = t.size();
s = "?" + s;
vector<int> v;
v.push_back(0);
for (int i = m;i <= n;i++)
if (s.substr(i - m + 1, m) == t) v.push_back(i);
vector<int> f(507, 0x3f3f3f3f), tot(507, 0);
f[0] = 0, tot[0] = 1;
for (int i = 1;i < v.size();i++) {
for (int j = i - 1;j >= 0;j--) {
if (v[i] - v[j] < m) continue;
bool ok = 1;
for (int k = j + 1;k < i;k++) ok &= v[k] - v[j] < m || v[i] - v[k] < m;
if (!ok) break;
if (f[i] > f[j] + 1) {
f[i] = f[j] + 1;
tot[i] = tot[j];
}
else if (f[i] == f[j] + 1) {
tot[i] = (tot[i] + tot[j]) % mod;
}
}
}
int mi = n, ans = 0;
for (int i = 0;i < v.size();i++) if (v.back() - v[i] < m) mi = min(mi, f[i]);
for (int i = 0;i < v.size();i++) if (v.back() - v[i] < m && f[i] == mi) ans = (ans + tot[i]) % mod;
cout << mi << ' ' << ans << '\n';
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

Codeforces Round #820 (Div. 3) A-G的更多相关文章

  1. Educational Codeforces Round 47 (Div 2) (A~G)

    目录 Codeforces 1009 A.Game Shopping B.Minimum Ternary String C.Annoying Present D.Relatively Prime Gr ...

  2. Educational Codeforces Round 46 (Div 2) (A~G)

    目录 Codeforces 1000 A.Codehorses T-shirts B.Light It Up C.Covered Points Count(差分) D.Yet Another Prob ...

  3. Educational Codeforces Round 45 (Div 2) (A~G)

    目录 Codeforces 990 A.Commentary Boxes B.Micro-World C.Bracket Sequences Concatenation Problem D.Graph ...

  4. Codeforces Round #582 (Div. 3)-G. Path Queries-并查集

    Codeforces Round #582 (Div. 3)-G. Path Queries-并查集 [Problem Description] 给你一棵树,求有多少条简单路径\((u,v)\),满足 ...

  5. Codeforces Round #368 (Div. 2)

    直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...

  6. Codeforces Round #279 (Div. 2) ABCDE

    Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems     # Name     A Team Olympiad standard input/outpu ...

  7. 贪心+模拟 Codeforces Round #288 (Div. 2) C. Anya and Ghosts

    题目传送门 /* 贪心 + 模拟:首先,如果蜡烛的燃烧时间小于最少需要点燃的蜡烛数一定是-1(蜡烛是1秒点一支), num[g[i]]记录每个鬼访问时已点燃的蜡烛数,若不够,tmp为还需要的蜡烛数, ...

  8. Codeforces Round #383 (Div. 2) 题解【ABCDE】

    Codeforces Round #383 (Div. 2) A. Arpa's hard exam and Mehrdad's naive cheat 题意 求1378^n mod 10 题解 直接 ...

  9. 模拟 Codeforces Round #249 (Div. 2) C. Cardiogram

    题目地址:http://codeforces.com/contest/435/problem/C /* 题意:给一组公式,一组数据,计算得到一系列的坐标点,画出折线图:) 模拟题:蛮恶心的,不过也简单 ...

随机推荐

  1. 基础1:JS的原型和原型链究竟

    JS的原型和原型链究竟是什么? 1. 从JS创建一个对象开始说起: 1.1 工厂模式创建对象 (缺点是无法知道创建出来的对象是一个什么类型的对象) function createPerson(name ...

  2. 图床搭建|chrome插件|操作简单不要钱

    为什么需要一个图床 为了写博客 图床:专门用来存放图片,同时允许你把图片对外连接的网上空间. 用markdown格式写作,插入图片需要图片的url地址,然后博客的背景图也是要用url地址. 有段时间, ...

  3. MPI学习笔记(三):矩阵相乘的分块并行(行列划分法)

    mpi矩阵乘法:C=αAB+βC 一.主从模式的行列划分并行法 1.实现方法 将可用于计算的进程数comm_sz分解为a*b,然后将矩阵A全体行划分为a个部分,将矩阵B全体列划分为b个部分,从而将整个 ...

  4. Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos

    目录 1. 接着上一篇 2. 思路 3. 下载Sentinel源码 4. 看Gateway里面读取的配置信息 5. 修改Sentinel控制台源码 6. 熔断规则测试 7. 限流规则测试 8. 打包使 ...

  5. Linux安装Jenkins及配置svn使用

    目录 1. 下载 2. 创建文件夹 3. 安装 4. 修改端口,不用这步 5. 安装插件提速 6. 启动 7. 页面访问 8. 新建用户 9. 安装Subversion插件 10. 安装maven插件 ...

  6. c语言_二叉树的建立以及3种递归

    二叉树c语言的实现 二叉树的建立 二叉树的数据结构 typedef struct node{    int data;    struct node* left;    struct node* ri ...

  7. Vben Admin 源码学习:状态管理-角色权限

    前言 本文将对 Vue-Vben-Admin 角色权限的状态管理进行源码解读,耐心读完,相信您一定会有所收获! 更多系列文章详见专栏   Vben Admin 项目分析&实践 . 本文涉及到角 ...

  8. 八皇后代码C语言版本

    y = x + b   ->    y-x = b   主对角线上,行下标与列下标之差相等y = -x + b  ->    y+x = b   副对角线上,行下标与列下标之和相等主对角线 ...

  9. C++ "链链"不忘@必有回响之单链表

    1. 前言 数组和链表是数据结构的基石,是逻辑上可描述.物理结构真实存在的具体数据结构.其它的数据结构往往在此基础上赋予不同的数据操作语义,如栈先进后出,队列先进先出-- 数组中的所有数据存储在一片连 ...

  10. Gimbal Lock欧拉角死锁问题

    技术背景 在前面几篇跟SETTLE约束算法相关的文章(1, 2, 3)中,都涉及到了大量的向量旋转的问题--通过一个旋转矩阵,给定三个空间上的欧拉角\(\alpha, \beta, \gamma\), ...