AtCoder Beginner Contest 367
A - Shout Everyday (abc367 A)
题目大意
高桥从睡到 ,如果在 时,他醒着,他则会对章鱼烧发癫,问他今天是否发癫。
解题思路
由于只有小时,直接枚举 ,看看是否遍历到 即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int a, b, c; cin >> a >> b >> c; bool ok = true; for (; a != b; a = (a + 1) % 24) { if (a == c) { ok = false; break; } } if (ok) cout << "Yes" << '\n'; else cout << "No" << '\n'; return 0; }
B - Cut .0 (abc367 B)
题目大意
给定一个小数,将末尾零删掉,如果小数部分删掉则把小数部分删掉。
解题思路
按照题意模拟即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); string s; cin >> s; while (s.back() == '0') s.pop_back(); if (s.back() == '.') s.pop_back(); cout << s << '\n'; return 0; }
C - Enumerate Sequences (abc367 C)
题目大意
输出所有符合要求的数组,满足
- 的和是 的倍数
- 的范围是
解题思路
用枚举所有的情况即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, k; cin >> n >> k; vector<int> a(n); for (auto& i : a) cin >> i; vector<int> ans(n); auto dfs = [&](auto&& self, int pos) -> void { if (pos == n) { if (accumulate(ans.begin(), ans.end(), 0) % k == 0) { for (auto i : ans) cout << i << " "; cout << '\n'; } return; } for (int i = 1; i <= a[pos]; ++i) { ans[pos] = i; self(self, pos + 1); } }; dfs(dfs, 0); return 0; }
D - Pedometer (abc367 D)
题目大意
环形湖的个点,给定 表示从第 个点顺时针走到第 个点的时间。
问对数 ,满足从 顺时针 ,使得其时间是的倍数。
解题思路
考虑的情况,其实就可以假象在一条数轴上,从左走到右的时间,这个时间其实就是 ,这里可以预处理出 的前缀和,其实就是换算成下标 ,那么从 ,就是 ,其差值是 的倍数 ,这个就意味着。所以统计 的对数,其实就是统计 的个数问题。
枚举 ,然后考虑有多少的 符合要求,而符合要求的 就是满足 ,所以用 维护的个数,那么枚举 ,符合要求的 的数量就是 。
而对于,考虑 的情况 可以把环形解成链再翻倍一下,即,后面的的位置就是,即偏移了一圈的距离。然后在枚举第二圈的时,维护的是第一圈的第一圈的 的 的数量。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m; cin >> n >> m; vector<int> a(n); for (auto& x : a) cin >> x; vector<int> cnt(m, 0); LL ans = 0; LL presum = 0; for (int i = 0; i < n; ++i) { ans += cnt[presum % m]; cnt[presum % m]++; presum += a[i]; } LL sum = presum; presum = 0; for (int i = 0; i < n; ++i) { cnt[presum % m]--; ans += cnt[sum % m]; sum += a[i]; presum += a[i]; } cout << ans << '\n'; return 0; }
E - Permute K times (abc367 E)
题目大意
给定数组,进行 次操作。
每次操作,求数组 ,然后 。
问 次操作后的数组 。
解题思路
题目其实可以抽象成,给定基环内向森林,点有点权。问从每个点出发,走了步后的点的点权。
其中边是,点权 。
由于图是固定的,问第 步后到达的点,预处理倍增数组 表示从点 出发走了 步后到达的点。
然后对于每个点用倍增数组求 次后的结果即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; LL k; cin >> n >> k; vector<vector<int>> run(64, vector<int>(n)); for (int i = 0; i < n; i++) { int v; cin >> v; --v; run[0][i] = v; } vector<int> a(n); for (auto& x : a) cin >> x; for (int i = 1; i < 64; i++) { for (int j = 0; j < n; j++) { run[i][j] = run[i - 1][run[i - 1][j]]; } } for (int i = 0; i < n; i++) { LL cnt = k; int cur = i; for (int j = 0; j < 64; j++) { if (cnt & (1LL << j)) { cur = run[j][cur]; } } cout << a[cur] << " \n"[i == n - 1]; } return 0; }
F - Rearrange Query (abc367 F)
题目大意
给定两个数组,回答 个问题。
每个问题给定 ,问 能否通过重排,等于 。
解题思路
如果能通过重排 ,首先得 ,然后看每个数的出现次数是否一致。显然这判断代价很大。
一个计算代价小的的必要条件是,但不是充分条件,会有误判的概率,会被精心构造的数据卡掉。
因为我们只要求数量相等,如果我们事先对所有数进行一个随机映射
,这个误判的概率将极大减小。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; unsigned rnd() { static unsigned A = 1 << 16 | 3, B = 33333331, C = 2341; return C = A * C + B; } int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, q; cin >> n >> q; vector<LL> a(n); vector<LL> b(n); map<int, LL> tr; for (auto& x : a) { cin >> x; if (tr.find(x) == tr.end()) { tr[x] = rnd(); } } for (auto& x : b) { cin >> x; if (tr.find(x) == tr.end()) { tr[x] = rnd(); } } auto presum = [&](vector<LL>& a) { int n = a.size(); vector<LL> s1(n + 1); for (int i = 0; i < n; ++i) { s1[i + 1] = (s1[i] + tr[a[i]]); } return s1; }; auto sa1 = presum(a); auto sb1 = presum(b); auto sum = [&](vector<LL>& s, int l, int r) { return (s[r] - s[l - 1]); }; auto check = [&](int l, int r, int L, int R) { auto SA = sum(sa1, l, r); auto SB = sum(sb1, L, R); return SA == SB; }; while (q--) { int l, r, L, R; cin >> l >> r >> L >> R; if (r - l == R - L && check(l, r, L, R)) { cout << "Yes" << '\n'; } else { cout << "No" << '\n'; } } return 0; }
G - Sum of (XOR^K or 0) (abc367 G)
题目大意
给定个数的数组,问 所有的个非空子序列的价值和。
一个序列 的价值定义如下:
- 如果个数是 的倍数,则价值是
- 否则价值是 。
解题思路
只会和 。
神奇的代码
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2017-08-17 JZOJ.5286【NOIP2017模拟8.16】花花的森林