CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes!)(A~C2)
A - Shohag Loves Mod
思路
假设构造差值是 \(x = 0,1,\dots ,n\) 这样的,那么只要让 \(a_i \equiv x \pmod{i}\) 即可,也就是 \(a_i = i+x\)。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int n; cin >> n; for (int i = 1; i <= n; i ++) { cout << i + i - 1 << " \n"[i == n]; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
B. Shohag Loves Strings
思路
其实只要找到形如 aa
和 abc
这种两个一样或三个不一样的就可以,但是很不懂啊,我最开始写得就是用 substr 去截取的,但是一直 \(WA\),后来索性就直接暴力搞了。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { string s; cin >> s; int n = s.size(); for (int len : {2, 3, 4, 5}) { for (int i = 0; i + len <= n; i ++) { set<string> t; for (int l = i; l < i + len; l ++) { for (int r = l; r < i + len; r ++) { t.insert(s.substr(l, r - l + 1)); } } if (t.size() % 2 == 0) { cout << s.substr(i, len) << "\n"; return; } } } cout << "-1\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
C1 - Shohag Loves XOR (Easy Version)
思路
题目给定范围 \(\sum n \le 1\times 10^7\),那么直接枚举找 \(y\) 即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int x; i64 m; cin >> x >> m; int ans = 0; for (int i = 1; i < x; i ++) { if ((x % i == 0 || (i ^ x) % i == 0 ) && x != (i ^ x) && (i ^ x) <= m) { ans ++; } } cout << ans << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
C2 - Shohag Loves XOR (Hard Version)
思路
唉唉,数学分类讨论题,感觉这题就应该和 \(D\) 题换个位置,赛时分析了一半看了一眼榜就去写 \(D\) 了,QWQ。
以下要用到的关于异或的性质,不作证明。
\(1、x-y\le x\oplus y \le x + y\)
\(2、x\oplus x = 0\)
\(3、x\oplus y = z \Rightarrow x = z \oplus y\)
设 \(p = x\oplus y\),考虑三种情况,\(p\) 被 \(x\) 整除,\(p\) 被 \(y\) 整除,\(p\) 被 \(\text{lcm}(x,y)\) 整除。
- \(p\) 被 \(x\) 整除的时候:
那么 \(y = p\oplus x,p = k\times x:\)\[\because 1\le y\le m\\\\ \therefore p\oplus x\le m\\\\ 且当 p\oplus x \le p + x \le m 时,p\le m-x\\\\ 那么 x 的倍数有 \left\lfloor\frac{m-x}{x}\right\rfloor 个.\\\\ 这里有两个 x 的倍数需要特殊讨论:\\\\ 一个是0,即当x\le m的时候,0是可取的;\\\\ 另一个是x,当x\le m-x的时候,会取到x为本身的倍数,但是x\oplus x=0<1,所以我们需要去掉.\\\\ 当 p\oplus x \ge p - x > m 时,p > m + x\\\\ 但是 y \le m,\therefore p\not\in(m+x,+\infty)\\\\ \therefore (m-x,m+x] 的范围内最多有两个 x 的倍数,直接枚举即可.\] - \(p\) 被 \(y\) 整除的时候:
- \(x<y:\)
\[\because x > 0\And y>0\\\\ \therefore p=x\oplus y \ne x \And p \ne y\\\\ \therefore 当y>x时,p至少为y的2倍\\\\ 但是 p\le x + y < 2\max(x,y)=2y\\\\ \therefore 此时不存在p.\]- \(x\ge y\)\[此时x\le 1\times 10^6,直接枚举即可. \]
- \(p\) 被 \(\text{lcm}(x,y)\) 整除的时候:
- \(x\ne y:\)\[此时\text{lcm}(x,y)\ge 2\max(x,y)\\\\ 但是由上述推导可知p < 2\max(x,y)\\\\ \therefore 此时不存在 p.\]
- \(x=y:\)
\[当x\le m 时,存在一个p. \] - \(x\ne y:\)
最后答案就是前两个情况的数量减去第三个情况的数量即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int x; i64 m; cin >> x >> m; i64 ans = max(m - x, 0LL) / x + (x <= m); ans -= (x <= m - x); for (i64 i = max(m - x, 0LL) + 1; i <= m + x; i++) { if (i % x == 0 && (i ^ x) <= m && (i ^ x) > 0) { ans ++; } } for (int i = 1; i <= min<i64>(x, m); i ++) { if ((i ^ x) % i == 0) { ans ++; } } cout << ans - (x <= m) << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
D - Shohag Loves GCD
思路
这题也是唐完了。
要使得 \(a_{\gcd(i,j)} \ne \gcd(a_i,a_j)\),且还要让 \(a\) 数组尽可能大,假设 \(a_i\) 是较大的数,那么只要让 \(i\) 的倍数取较小的值即可,但是这里可能会存在问题就是,比如 \(2\) 的倍数 \(4\) 和 \(8\) 又不能填一样的,这里其实就用到了欧拉筛的思想,每个合数都只会被它最小质因数的另一个因子筛掉,这样就可以保证当后面的数对存在 \(\gcd \ne\) 当前 \(i\) 的时候及时退出了,时间复杂度是 \(\mathcal{O}(n)\)。
当然这个题还有另外一种思路,就是对于每一个 \(i\) 来说,都去直接枚举 \(i\) 的倍数,然后后面的数的倍数又会把前面的某些数的倍数给覆盖掉,也能保证每个数的倍数的 \(a_i\) 的 \(\gcd\) 不会与前面重合,时间复杂度是调和级数级别,也就是 \(\mathcal{O}(n\ln n)\)。
不过在 \(cf\) 上貌似两种写法也没有太大的时间差距,跑得都很快就是了。
代码(欧拉筛写法)
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int n, m; cin >> n >> m ; set<int> s; vector<int> a(m + 1); for (int i = 1; i <= m; i ++) { cin >> a[i]; } sort(a.begin() + 1, a.end(), greater<>()); vector<array<int, 2>> ans(n + 1, {0, 0}); ans[1] = {a[1], 1}; vector<int> pr; for (int i = 2; i <= n; i ++) { if (!ans[i][0]) { if (m < 2) { cout << "-1\n"; return ; } pr.emplace_back(i); ans[i] = {a[2], 2}; } for (int j = 0; j < pr.size() && pr[j] <= n / i; j ++) { if (m < ans[i][1] + 1) { cout << "-1\n"; return; } ans[i * pr[j]] = {a[ans[i][1] + 1], ans[i][1] + 1}; if (i % pr[j] == 0) break; } } for (int i = 1; i <= n; i ++) { cout << ans[i][0] << " \n"[i == n]; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t = 1; cin >> t; while (t--) { solve(); } return 0; }
代码(枚举倍数)
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int n, m; cin >> n >> m ; set<int> s; vector<int> a(m + 1); for (int i = 1; i <= m; i ++) { cin >> a[i]; } sort(a.begin() + 1, a.end(), greater<>()); vector<array<int, 2>> ans(n + 1, {0, 0}); ans[1] = {a[1], 1}; vector<int> pr; for (int i = 2; i <= n; i ++) { if (!ans[i][0]) { if (m < 2) { cout << "-1\n"; return ; } pr.emplace_back(i); ans[i] = {a[2], 2}; } for (int j = i + i; j <= n; j += i) { if (m < ans[i][1] + 1) { cout << "-1\n"; return; } ans[j] = {a[ans[i][1] + 1], ans[i][1] + 1}; } } for (int i = 1; i <= n; i ++) { cout << ans[i][0] << " \n"[i == n]; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t = 1; cin >> t; while (t--) { solve(); } return 0; }
本文作者:Ke_scholar
本文链接:https://www.cnblogs.com/Kescholar/p/18568541
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2023-11-28 Codeforces Round 911 (Div. 2) D