Codeforces Round #792 (Div. 1 + Div. 2) A-E

A

题目

https://codeforces.com/contest/1684/problem/A

题解

思路

知识点:数学。

显然长度大于等于3的数字串的最小数位是完全可以通过这些操作留到最后。

长度等于2的数字串只可能是个位数字。

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

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

代码

#include <bits/stdc++.h>

using namespace std;

int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
string str;
cin >> str;
if (str.length() == 2) cout << str.back() << '\n';
else {
int ans = ~(1 << 31);
for (int i = 0;i < str.length();i++) ans = min(ans, str[i] - '0');
cout << ans << '\n';
}
}
return 0;
}

B

题目

https://codeforces.com/problemset/problem/1684/B

题解

思路

知识点:数学,构造。

容易得到三个式子

\[x &= ky + a\\
y &= mz + b\\
z &= nx + c\\
\]

其中 \(k,m,n \in \mathbb{N^+}\)。

通过代入得到

\[x = \frac{kmc + kb + a}{1 - kmn}
\]

由于 \(z \mod x = c\) ,因此有 \(x > c\) ,考虑 \(k = 1,m = 1,n = 0\) 得到 \(x = a+b+c , y = b+c , z = c\) 。

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

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

代码

#include <bits/stdc++.h>

using namespace std;

int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
long long a, b, c;
cin >> a >> b >> c;
cout << a + b + c << ' ' << b + c << ' ' << c << '\n';
}
return 0;
}

C

题目

https://codeforces.com/problemset/problem/1684/C

题解

思路

知识点:模拟,排序。

通过排序完数组和原来的对比数组,找到第一组两个在同一行需要交换位置的点,如果超过2个同一行的需要交换的点说明一次交换不可行直接输出-1,如果为0个则不需要交换,设置任意一个点作为两个交换的点(即不交换)。

在确认两个交换点之后,对原数组每行进行交换,每行交换之后判断是否是排序好的,如果有一行不是说明不可行输出-1,否则为答案。

时间复杂度 \(O(nm \log m)\)

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

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; bool solve() {
int n, m;
cin >> n >> m;
vector<vector<int>> a(n, vector<int>(m)), b(n, vector<int>(m));
for (int i = 0;i < n;i++) {
for (int j = 0;j < m;j++) {
cin >> a[i][j], b[i][j] = a[i][j];
}
}
for (int i = 0;i < n;i++) {
sort(b[i].begin(), b[i].end());
}
int pos1 = -1, pos2 = -1;
for (int i = 0;i < n;i++) {
for (int j = 0;j < m;j++) {
if (a[i][j] != b[i][j]) {
if (!~pos1) pos1 = j;
else if (!~pos2) pos2 = j;
else return false;
}
}
if (~pos1) break;
}
if (!~pos1) pos2 = pos1 = 0;
for (int i = 0;i < n;i++) {
swap(a[i][pos1], a[i][pos2]);
if (!is_sorted(a[i].begin(), a[i].end())) return false;
}
cout << pos1 + 1 << ' ' << pos2 + 1 << '\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

题目

https://codeforces.com/contest/1684/problem/D

题解

思路

知识点:贪心(贪给我使劲贪)。

结论:跳过以 \(n-1-i-a[i]\) 排序的前 \(k\) 小值的点,或者说是 \(i+a[i]\) 排序的前 \(k\) 大值的点。

意识流证明:

\(n-1-i-a[i]\) 可以理解为跳过一个点后的代价改变量(\(i+a[i]\) ,即 \(a[i]-(n-1-i)\) 可以理解为跳过一个点的代价减少量),而只要选改变量最小的 \(k\) 个点,并且减去在每个跳过的点因为之前跳过点产生的额外代价(跳过的点不应该有代价)共 \(k(k-1)/2\) ,可以得到一个最小实际改变量(实际上一定存在一种方法使其小于 \(0\) ,这也说明了最优方法一定把 \(k\) 次跳过机会用完),加上改变量就能使总代价最小。

数学证明:微扰法。

假设方案不是跳过最小改变量的 \(k\) 个位置,则存在更优方案。

首先,存在某个位置 \(i\) 没有被跳过,某个位置 \(j\) 被跳过,且有 \(n-1-i-a[i]<n-1-j-a[j]\),即 \(i+a[i]>j+a[j]\) ,有两种情况\(i<j\) 和 \(i>j\) 。

当 \(i<j\) 时,从 \(a[j]\) 到 \(a[i]\) 会让 \(j-i\) 个位置代价加一,并且答案减去 \(a[i]\) 加上 \(a[j]\),又因为 \(i+a[i]>j+a[j]\) , 可以得到改变量 \(a[j] - a[i] + j - i < 0\) ,改变一定更优。\(i>j\) 的情况同理。

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

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

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; int a[200007]; bool solve() {
int n, k;
cin >> n >> k;
///显然k个跳点都选上是最小的必要条件
ll ans = -1LL * k * (k - 1) / 2;///每个跳过的点都要减掉之前跳过点产生的额外代价,因为跳过的点没有代价
for (int i = 0;i < n;i++) cin >> a[i], ans += a[i], a[i] = n - 1 - i - a[i];///n-i-a[i]代表跳过这个点相对于不跳过会产生多少代价
sort(a, a + n);///用于挑选前k个产生代价最小的点跳过
for (int i = 0;i < k;i++) ans += a[i];///跳过产生的代价变化
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

题目

https://codeforces.com/contest/1684/problem/E

题解

思路

知识点:数据结构,贪心。

MEX:序列中最小未出现的自然数(包括0)。

例如,\(MEX(\{ 0,1,2,4,5 \})=3\) , \(MEX(\{ 1,2,4,5 \}) = 0\) 。

观察\(DIFF - MEX\) 的结果,发现 \(MEX\) 数之前的数必然都出现,则种类数一定和 \(MEX\) 一样,因此结果就是大于 \(MEX\) 的数的种类数。

我们发现,当通过修改数字使得 \(MEX\) 增大时,\(DIFF\) 必然是不增的,因此可以先考虑在 \(k\) 次操作得到尽可能大的 \(MEX\) ,而数组长度为 \(n\) ,则必然可以通过修改使在 \(n\) 以内的所有 \(MEX\) 都能得到,所以可以从 \(0\) 开始遍历 ,若存在该数字则继续,否则通过一次操作得到这个数字,这样就可以得到 \(k\) 次操作后最大可能的 \(MEX\) 了,这样操作得到的 \(MEX\) 可能会大于 \(n\) 但不需要限制操作次数使其合法,因为大于等于 \(n\) 在之后处理中也都能得到正确结果 \(0\) 。

得到最大的 \(MEX\) 后,只要考虑操作比 \(MEX\) 大的就行(即使可能用不完 \(k\) 次),首先因为大于 \(MEX\) 的数字种类即是答案,所以优先取完其尽可能多的种类能直接降低答案,其次 \(MEX\) 是操作 \(k\) 次内的必然结果,无论如何都能在 \(k\) 次内达到,而大于 \(MEX\) 的数字种类即是答案,那么只考虑 \(k\) 次操作后(可能不到 \(k\) 次就取完了,剩下的操作可以理解为用小于 \(MEX\) 的数补全,从而也能达到 \(MEX\) ,但不改变答案 \(0\))这些数的种类即可。特别地,最大 \(MEX\) 在取的时候可能大于等于其最大可能值 \(n\) ,即最后大于 \(MEX\) 数的种类必然为\(0\) ,也即 \(k\) 次操作内必然取完大于 \(MEX\) 的数,答案也为 \(0\) ,所以在之前的操作不需要通过限制操作次数来限制 \(MEX\) 。

时间复杂度 \(O(n \log^2 n)\)

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

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; bool solve() {
int n, k;
cin >> n >> k;
map<int, int> m;///用于元素与数量映射
for (int i = 0;i < n;i++) {
int tmp;
cin >> tmp;
m[tmp]++;
}
int mex = 0;
for (int i = 0, kk = k;;i++) {
if (!m.count(i)) {
if (kk) kk--;
else {
mex = i;
break;
}
}
}
priority_queue<int, vector<int>, greater<int>> pq;
for (auto i : m) if (i.first > mex) pq.push(i.second);
while (!pq.empty() && k >= pq.top()) { ///答案等于大于mex的元素种类,所以k<最小个数元素时,不用继续,此种类补全k次后不会消失,留着就行
k -= pq.top();
pq.pop();
}
cout << pq.size() << '\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 #792 (Div. 1 + Div. 2) A-E的更多相关文章

  1. Codeforces Round #792 (Div. 1 + Div. 2) // C ~ E

    比赛链接:Dashboard - Codeforces Round #792 (Div. 1 + Div. 2) - Codeforces C. Column Swapping 题意: 给定一个n*m ...

  2. Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...

  3. Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)

    Problem   Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...

  4. Educational Codeforces Round 43 (Rated for Div. 2)

    Educational Codeforces Round 43 (Rated for Div. 2) https://codeforces.com/contest/976 A #include< ...

  5. Educational Codeforces Round 35 (Rated for Div. 2)

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  6. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  7. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

  8. Educational Codeforces Round 63 (Rated for Div. 2) 题解

    Educational Codeforces Round 63 (Rated for Div. 2)题解 题目链接 A. Reverse a Substring 给出一个字符串,现在可以对这个字符串进 ...

  9. Educational Codeforces Round 39 (Rated for Div. 2) G

    Educational Codeforces Round 39 (Rated for Div. 2) G 题意: 给一个序列\(a_i(1 <= a_i <= 10^{9}),2 < ...

随机推荐

  1. gnome shell 扩展命令行开启和关闭

    #关闭 gnome-shell-extension-tool -d 扩展名 #开启 gnome-shell-extension-tool -e 扩展名 例如: gnome-shell-extensio ...

  2. Linux编译安装-软件

    编译源码的项目工具 C.C++的源码编译:使用make项目管理器 configure脚本 --> Makefile.in --> Makefile 相关开发工具: autoconf: 生成 ...

  3. Java SPI 和 API,傻傻分不清?

    最近新写了一个中间件「运行时动态日志等级开关」,其中使用Java SPI机制实现了自定义配置中心,保证良好的扩展性. 项目地址,走过路过可以点个star :)https://github.com/sa ...

  4. python使用虚拟环境venv

    venv模块支持使用自己的站点目录创建轻量级"虚拟环境",可选择与系统站点目录隔离.每个虚拟环境都有自己的Python二进制文件(与用于创建此环境的二进制文件的版本相匹配),并且可 ...

  5. 阿里新零售中的智能补货(I)— 库存模型

    文章作者:阿里零售通算法团队 出品社区:DataFun 导读: 零售通作为阿里巴巴新零售的八路大军之一,肩负着"共建智能分销平台"和"让百万小店拥抱DT时代"的 ...

  6. 这 BUG,绝了

    上周只上了三天班,但我也丝毫不敢懈怠,BUG 更是一个也没少写. 看着满屏幕的 ERROR,我陷入沉思.为什么我写的代如此烂,无法像大牛们写的那般优雅? 越想越自卑,越想越抑郁.我觉得这样不行,一定得 ...

  7. Nacos源码系列—订阅机制的前因后果(下)

    点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 nacos,即可免费获取源码 事件发布 在上一节中我们讲解了在Noti ...

  8. 用 notion 管理信用卡与花呗

    用 notion 管理信用卡与花呗 Notion原文,排版更佳 概述 不需要提醒功能和安卓用户可以忽略Scriptable和快捷指令 app的设置 Notion 建立信用卡表格,录入信用卡基本信息,自 ...

  9. 第30章 LeetCode 72 编辑距离

    每日一句 A flower cannot blossom without sunshine, and man cannot live without love. 花没有阳光就不能盛开,人没有爱就不能生 ...

  10. 最大流&最小割&费用流模版

    好久都没有搞博客了.想认真写又要准备文化课期末了. ISAP 流程: 原理就是dfs找增广路. 最基础的建反向边以便反悔就不说了. 但是记录一个dep(dis)表示层数,一开始BFS(从t开始,dis ...