A – Keanu Reeves
子串分割,要求个数最少,并且每个子串满足0和1的个数不同。先统计整个串中的1的个数和0的个数,如果不同,直接输出;否则,最后一个单独为一串,前$|s|-1$个为一串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int MAX_N = 100 + 5; int n, pre[MAX_N], cnt; char s[MAX_N]; int main() { scanf("%d", &n); scanf("%s", s); for (int i = 0; i < n; ++i) cnt += (s[i] == '1'); if (cnt * 2 != n) { puts("1"); puts(s); } else { puts("2"); for (int i = 0; i < n - 1; ++i) { putchar(s[i]); } putchar(' '); putchar(s[n - 1]); puts(""); } return 0; } |
B – Number Circle
对原串排序后,前$n-1$个一定满足$a_i > a_{i+1} + a_{i – 1}$,交换$a_n$和$a_{n-1}$,如果满足交换前$a_n < a_{n-1}+ a_{n-2}$,则交换后是合法的,因为$a_n + a_1 > a_{n-1}$一定成立。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int MAX_N = 100000 + 5; int n, a[MAX_N]; int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", a + i); sort(a + 1, a + n + 1); swap(a[n - 1], a[n]); if (a[n - 1] >= a[n] + a[n - 2]) puts("NO"); else { puts("YES"); for (int i = 1; i <= n; ++i) { printf("%d%c", a[i], (i == n ? '\n' : ' ')); } } return 0; } |
C – Candies!
因为长度为$2$的幂次,所以总状态不超过$n \log n$种,记忆化搜索即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include <bits/stdc++.h> using namespace std; const int MAX_N = 100000 + 5; int n, q, qL, qR, a[MAX_N]; map < pair <int, int>, pair <int, int> > f; pair <int, int> cal(int l, int r) { if (f.find(make_pair(l, r)) != f.end()) return f[make_pair(l, r)]; if (l == r) { f[make_pair(l, r)] = make_pair(a[l], 0); return f[make_pair(l, r)]; } int mid = (l + r) >> 1; pair <int, int> lSum = cal(l, mid), rSum = cal(mid + 1, r); int add = 0; if (lSum.first + rSum.first >= 10) add = 1; f[make_pair(l, r)] = make_pair((lSum.first + rSum.first) % 10, lSum.second + rSum.second + add); return f[make_pair(l, r)]; } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", a + i); scanf("%d", &q); for (int i = 1; i <= q; ++i) { scanf("%d%d", &qL, &qR); pair <int, int> ans = cal(qL, qR); printf("%d\n", ans.second); } return 0; } |
D1 – Add on a Tree
如果一个非叶子节点$u$链接了一个叶子节点$x$和一个非叶子节点$v$,那么如果不连接其他边,$(u,x)$和$(u,v)$的权是相等的,当$u$连出另外一条边$(u, y)$,它一定会伸向另一个叶子结点,可以打破这个性质。所以非叶子节点的度应该大于2。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int MAX_N = 100000 + 5; int n, deg[MAX_N]; inline bool check() { for (int i = 1; i <= n; ++i) { if (deg[i] == 1 || deg[i] > 2) { continue; } else { return false; } } return true; } int main() { scanf("%d", &n); int u, v; for (int i = 1; i <= n - 1; ++i) { scanf("%d%d", &u, &v); ++deg[u], ++deg[v]; } puts(check() ? "YES" : "NO"); return 0; } |
E – Count Pairs
$(a_i + a_j) (a_i ^2 +a_j^2) \equiv k \pmod{p}$,两边同时乘以$a_i – a_j$,整理后得到以下式子:
$$ a_i ^ 4 – ka_i \equiv a_j ^ 4 – ka_j \pmod{p} $$
统计$f(a_i) = a_i ^ 4 – ka_i \pmod{p} $函数值相同的$i$的个数$c_i$,每个函数值对答案的贡献为$c_i \choose 2$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int MAX_N = 300000 + 5; int n, p, k; int a[MAX_N]; map <int, int> h; int main() { scanf("%d%d%d", &n, &p, &k); for (int i = 1; i <= n; ++i) { scanf("%lld", a + i); LL trans = LL(LL(a[i]) * a[i] % p) * LL(LL(a[i]) * a[i] % p) % p; trans = trans - LL(k) * a[i]; trans = (trans % p + p) % p; h[trans]++; } LL ans = 0; for (auto x: h) { ans += x.second * (x.second - 1) / 2; } printf("%lld\n", ans); return 0; } |
说点什么