Codeforces Round #846 (Div. 2) A-E
A
题意
给 个正整数,找到三个数,使得他们的和为奇数,输出他们的下标。
题解
知识点:贪心。
找到三个奇数或者一个奇数两个偶数即可,其他情况无解。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; bool solve() { int n; cin >> n; vector<int> v1, v2; for (int i = 1;i <= n;i++) { int x; cin >> x; if (x & 1) v1.push_back(i); else v2.push_back(i); } if (v1.size() >= 3) { cout << "YES" << '\n'; cout << v1[0] << ' ' << v1[1] << ' ' << v1[2] << '\n'; } else if (v1.size() >= 1 && v2.size() >= 2) { cout << "YES" << '\n'; cout << v1[0] << ' ' << v2[0] << ' ' << v2[1] << '\n'; } else return false; 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 << "NO" << '\n'; } return 0; }
B
题意
给 个正整数 。选择一个 ,随后将 分成 个连续非空段,使得每段的和 的最大公约数 最大。
题解
知识点:数论,贪心。
对于任意 的任意划分有答案 ,根据 ,即 和 的最大公因数一定也是 的因子,那么 ,所以任意两段合并代替合并前的两段不会让答案变差,因此最好的情况一定出现在只分为两段的情况。
因此,我们只要求出 即可。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; ll a[200007]; bool solve() { int n; cin >> n; for (int i = 1;i <= n;i++) cin >> a[i], a[i] += a[i - 1]; ll ans = 1; for (int i = 1;i <= n - 1;i++) { ans = max(ans, gcd(a[i], a[n] - 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; }
C
题有问题。
D
题意
有一个数字 ,告诉你 的二进制位 的个数 。
随后可以执行不超过 次操作:选择一个 ,使得 减去 ,得到新的 的二进制位 的个数 。
最后,你需要猜出 是多少。
题解
知识点:位运算,枚举。
由于 最多会有 个 ,我们可以探测每一位是否为 。
具体的说,我们探测第 位是否为 ,可以减去 。如果这位是 ,那么新的个数 ,否则一定有 。但是,这个结论的前提是,我们是对原本的 做减法。考虑到操作会改变 ,因此我们第 位探测完后,第 位的探测减去的应该是 ,这样可以抵消上一次操作,等效于对原来的 减去 。
要注意的是,如果减的数超过 那么也会错,即我们不能探测超过 最高位二进制的数。为了防止超出,我们可以记录探测为 的位数 ,如果 那么可以立刻停止,因为此时答案已经满足要求了。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; int query(int x) { int cnt; cout << "- " << x << endl; cin >> cnt; return cnt; } void answer(int n) { cout << "! " << n << endl; } bool solve() { int cnt; cin >> cnt; int ans = 0, tot = 0; if (query(1) < cnt) ans += 1, tot++; for (int i = 1;i < 30 && tot < cnt;i++) { if (query((1 << i) - (1 << (i - 1))) < cnt) ans += 1 << i, tot++; } answer(ans); 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
题意
给定一个区间 ,求 的种类,其中 。
题解
知识点:整除分块。
设 我们考虑讨论 的大小:
- 当 ,那么对于最小的倍数 ,也一定有 , 所以不存在 的数满足这个范围的 。
- 当 ,我们一定可以构造 ,其中 。
- 当 ,我们尝试构造大于等于 的最小的一组数 ,这两个数满足 ,则 是合法的,否则一定不合法。
对于前两类我们可以轻易求出个数,但第三类,显然我们不可能一个一个枚举 。
实际上,我们发现会存在许多连续区间的 ,其 的值是一样的,大约有 个。假设 区间的 满足 ,那么若 满足 则构造的数不会超 ,是合法的。
那么这个问题现在就变成一个整除分块问题,为了方便,我们把取上整都转化为取下整,即 。已知左端点 和 ,求最大的右端点 满足 。为了在 的基础上将 向上逼近,我们将整除等式转化一个不等式 , 即为 的最大值 。
现在我们就可以从 开始枚举,每次可以枚举一个区间。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; bool solve() { ll L, R; cin >> L >> R; ll ans = max(0LL, R / 2 - L + 1); for (int l = 1, r;l < L;l = r + 1) { int k = (L - 1) / l; r = (L - 1) / k; ans += max(0LL, min((ll)r, R / (k + 2)) - l + 1); } 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; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17068334.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)