Codeforces Round #792 (Div. 1 + Div. 2) A-E
A
题解
知识点:数学。
显然长度大于等于3的数字串的最小数位是完全可以通过这些操作留到最后。
长度等于2的数字串只可能是个位数字。
时间复杂度
空间复杂度
代码
#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
题解
知识点:数学,构造。
容易得到三个式子
其中 。
通过代入得到
由于 ,因此有 ,考虑 得到 。
时间复杂度
空间复杂度
代码
#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
题解
知识点:模拟,排序。
通过排序完数组和原来的对比数组,找到第一组两个在同一行需要交换位置的点,如果超过2个同一行的需要交换的点说明一次交换不可行直接输出-1,如果为0个则不需要交换,设置任意一个点作为两个交换的点(即不交换)。
在确认两个交换点之后,对原数组每行进行交换,每行交换之后判断是否是排序好的,如果有一行不是说明不可行输出-1,否则为答案。
时间复杂度
空间复杂度
代码
#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
题解
知识点:贪心(贪给我使劲贪)。
结论:跳过以 排序的前 小值的点,或者说是 排序的前 大值的点。
意识流证明:
可以理解为跳过一个点后的代价改变量( ,即 可以理解为跳过一个点的代价减少量),而只要选改变量最小的 个点,并且减去在每个跳过的点因为之前跳过点产生的额外代价(跳过的点不应该有代价)共 ,可以得到一个最小实际改变量(实际上一定存在一种方法使其小于 ,这也说明了最优方法一定把 次跳过机会用完),加上改变量就能使总代价最小。
数学证明:微扰法。
假设方案不是跳过最小改变量的 个位置,则存在更优方案。
首先,存在某个位置 没有被跳过,某个位置 被跳过,且有 ,即 ,有两种情况 和 。
当 时,从 到 会让 个位置代价加一,并且答案减去 加上 ,又因为 , 可以得到改变量 ,改变一定更优。 的情况同理。
时间复杂度
空间复杂度
代码
#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
题解
知识点:数据结构,贪心。
MEX:序列中最小未出现的自然数(包括0)。
例如, , 。
观察 的结果,发现 数之前的数必然都出现,则种类数一定和 一样,因此结果就是大于 的数的种类数。
我们发现,当通过修改数字使得 增大时, 必然是不增的,因此可以先考虑在 次操作得到尽可能大的 ,而数组长度为 ,则必然可以通过修改使在 以内的所有 都能得到,所以可以从 开始遍历 ,若存在该数字则继续,否则通过一次操作得到这个数字,这样就可以得到 次操作后最大可能的 了,这样操作得到的 可能会大于 但不需要限制操作次数使其合法,因为大于等于 在之后处理中也都能得到正确结果 。
得到最大的 后,只要考虑操作比 大的就行(即使可能用不完 次),首先因为大于 的数字种类即是答案,所以优先取完其尽可能多的种类能直接降低答案,其次 是操作 次内的必然结果,无论如何都能在 次内达到,而大于 的数字种类即是答案,那么只考虑 次操作后(可能不到 次就取完了,剩下的操作可以理解为用小于 的数补全,从而也能达到 ,但不改变答案 )这些数的种类即可。特别地,最大 在取的时候可能大于等于其最大可能值 ,即最后大于 数的种类必然为 ,也即 次操作内必然取完大于 的数,答案也为 ,所以在之前的操作不需要通过限制操作次数来限制 。
时间复杂度
空间复杂度
代码
#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; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16296795.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧