Codeforces Round 973 (Div. 2)
写在前面
比赛地址:https://codeforces.com/contest/2013。
最后 3min 绝杀 E 上分场爽,然而前期太唐了呃呃要是不唐准能红名表现分。
妈的什么时候上黄!
A 签到
复制复制// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long //============================================================= //============================================================= //============================================================= int main() { //freopen("1.txt", "r", stdin); std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { int n, x, y, ans; std::cin >> n >> x >> y; if (x < y) { ans = ceil(1.0 * n / x); } else { ans = ceil(1.0 * n / y); } std::cout << ans << "\n"; } return 0; }
B 结论,贪心
发现第 个人会且一定会和第 个人打,则最终的 中一定有贡献 。
然后考虑到 ,则答案的上界即令所有 对 的贡献均为正值
发现仅需令 先分别和 打,再令 和 打即可达到上界。则答案即为:
// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long const int kN = 2e5 + 10; //============================================================= int n; LL a[kN]; //============================================================= //============================================================= int main() { //freopen("1.txt", "r", stdin); std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { std::cin >> n; LL sum = 0; for (int i = 1; i <= n; ++ i) std::cin >> a[i]; for (int i = 1; i < n - 1; ++ i) sum += a[i]; std::cout << a[n] - a[n - 1] + sum << "\n"; } return 0; }
C 交互
考虑每次往后面接一个字符并询问,若为真则固定该位,否则更换字符再询问,直至往后接 0/1 询问都为假。
发现此时的字符串一定为原串的一个后缀,然后考虑再往前不断接一个字符并询问,若为真则固定该位,否则可以保证该位一定为另一个字符。
易证操作数量不超过 次。
// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long //============================================================= int n; std::map <std::string, bool> checked; //============================================================= bool query(std::string &t_) { if (checked.count(t_)) return checked[t_]; std::cout << '?' << " " << t_ << "\n"; std::cout.flush(); bool ret; std::cin >> ret; return ret; } //============================================================= int main() { //freopen("1.txt", "r", stdin); // std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { std::cin >> n; std::string s; checked.clear(); while ((int)s.length() < n) { s.push_back('0'); bool ret = query(s); checked[s] = ret; if (ret) continue; s.pop_back(), s.push_back('1'); ret = query(s); checked[s] = ret; if (ret) continue; s.pop_back(); break; } while ((int) s.length() < n) { std::string t = "0" + s; bool ret = query(t); checked[t] = ret; if (ret) { s = t; continue; } s = "1" + s; } std::cout << '!' << " " << s << "\n"; std::cout.flush(); } return 0; }
D 贪心 or 二分答案
由给定的操作可知,显然存在一种最优方案,使得给定数列单调不降。
在这种限制下考虑使所有位置尽可能平均以最小化极差。
考虑对仅前 个位置操作后,其中的最小值的下界(不一定出现在位置 ),显然为:
考虑仅对后 个位置操作后,其中的最大值的上界(同样不一定出现在位置 ),显然为:
然后考虑到对整个数列进行操作,发现对整个数列操作后,可以达到的上下界即对上述的下界取最小值,对上界取最大值,则答案即为:
总时间复杂度 级别。
还有大力二分答案的做法,详见其他题解。
// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long const int kN = 2e5 + 10; //============================================================= int n; LL a[kN]; //============================================================= //============================================================= int main() { // freopen("1.txt", "r", stdin); std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { std::cin >> n; for (int i = 1; i <= n; ++ i) std::cin >> a[i]; LL s = 0, mina = a[1], maxa = 0; for (int i = 1; i <= n; ++ i) { s += a[i], mina = std::min(mina, s / i); } s = 0; for (int i = n; i; -- i) { s += a[i], maxa = std::max(maxa, (LL) ceil(1.0 * s / (n - i + 1))); } std::cout << maxa - mina << "\n"; } return 0; }
E 贪心,数学,gcd
发现两个不相等的数 取 ,一定有 ,即每次向序列后面加一个数,前缀的 都至少会除 2,则发现仅需通过不超过 个数,即可令前缀 快速地减小到全局 。
则显然第一个位置一定放全局最小值,否则根据 的算数基本定理的形式,全局最小值一定对质因数的幂次限制最多,则总可以通过调整使得全局最小值提前,使得总代价更小。
然后考虑每次 地枚举向序列后面加的数并取使 减小的最多的加上去即可,若加上后变为全局 则可直接停止枚举。
总时间复杂度 级别。
赛时根据 的性质找了一堆优化常数的小结论实际上并无必要呃呃,上面的关键结论出来直接大力做就过了。
// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long const int kN = 1e5 + 10; //============================================================= int n, a[kN]; LL alld, ans; //============================================================= //============================================================= int main() { // freopen("1.txt", "r", stdin); std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { std::cin >> n; ans = alld = 0; for (int i = 1; i <= n; ++ i) { std::cin >> a[i]; alld = std::__gcd(alld, 1ll * a[i]); } std::sort(a + 1, a + n + 1); int nowd = a[1]; ans += nowd; for (int i = 2; i <= n; ++ i) { if (nowd == alld) { ans += 1ll * alld * (n - i + 1); break; } int newd = nowd; for (int j = 1; j <= n; ++ j) { newd = std::min(newd, std::__gcd(nowd, a[j])); } nowd = newd, ans += nowd; } std::cout << ans << "\n"; } return 0; } /* 1 3 10 15 6 1 5 6 42 12 52 20 */
F1
什么东西我去
写在最后
学到了什么:
- D:感觉是平均所有位置最小化极差的套路。
- E:gcd 的单调性,最近碰到好几次了呃呃
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧