2021暑假模拟赛6
A[ABC172B(20)]
计算多少个对应的位置不同即可。
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); string s, t; cin >> s >> t; int ans = 0; for(int i = 0; i < s.size(); ++i) { ans += (s[i] != t[i]); } cout << ans << '\n'; return 0; }
B[HDU6986(1500)]
考虑一个常见维护不同颜色数的套路,开一个桶,如果一个颜色第一次加进来那么总数加$1$,如果颜色删没了总数减$1$,然后每次$dfs$维护这个桶即可。
#include <bits/stdc++.h> using namespace std; const int P1 = 1e9 + 7; const int P2 = 1e9 + 9; const int seed = 19560929; int main() { int T; scanf("%d", &T); while (T --> 0) { int N; scanf("%d", &N); vector<vector<int>> adj(N); for (int i = 1; i < N; ++i) { int P; scanf("%d", &P); P --; adj[P].push_back(i); adj[i].push_back(P); } vector<int> C(N); for (int i = 0; i < N; ++i) { scanf("%d", &C[i]); C[i] --; } vector<long long> pw1(N + 1); vector<long long> pw2(N + 1); pw1[0] = 1; pw2[0] = 1; for (int i = 0; i < N; ++i) { pw1[i + 1] = pw1[i] * seed % P1; pw2[i + 1] = pw2[i] * seed % P2; } long long Ans1 = 0; long long Ans2 = 0; vector<int> cnt(N); int tot = 0; auto dfs = [&] (auto &&f, int X, int F) -> void { cnt[C[X]] ++; if (cnt[C[X]] == 1) { tot ++; } Ans1 += 1LL * tot * pw1[X]; Ans1 %= P1; Ans2 += 1LL * tot * pw2[X]; Ans2 %= P2; for (int Y : adj[X]) { if (Y != F) { f(f, Y, X); } } cnt[C[X]] --; if (cnt[C[X]] == 0) { tot --; } }; for (int S = 0; S < N; ++S) { Ans1 = 0; Ans2 = 0; dfs(dfs, S, -1); printf("%lld %lld\n", Ans1, Ans2); } } }
C[CF1554D(1800)]
需要一个观察,观察出长为$n$的全$a$串和长度为$n+1$的全$a$串连起来是可行的,那么分类讨论中间需要接几个字符即可。
#include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; while (T --> 0) { int N; cin >> N; if (N == 1) { cout << 'a' << '\n'; continue; } if (N % 2 == 0) { int X = (N - 1) / 2; int Y = N - 1 - X; string Ans = ""; for (int i = 0; i < X; ++i) { Ans += 'a'; } Ans += 'b'; for (int i = 0; i < Y; ++i) { Ans += 'a'; } cout << Ans << '\n'; } else { int X = (N - 2) / 2; int Y = N - 2 - X; string Ans = ""; for (int i = 0; i < X; ++i) { Ans += 'a'; } Ans += 'b'; Ans += 'c'; for (int i = 0; i < Y; ++i) { Ans += 'a'; } cout << Ans << '\n'; } } }
D[CF1156C(2000)]
思考一下容易得出几个性质:答案不超过$\frac{n}{2}$,并且选择区间左端点肯定尽量靠左好。那么问题简单了,左端点肯定是左边连续的一段,右端点肯定是右边连续的一段,于是利用单调性求出答案即可。
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, z; cin >> n >> z; vector<int> x(n); for (int i = 0; i < n; ++i) { cin >> x[i]; } sort(x.begin(), x.end()); int l = -1; int r = n / 2 + 1; while (r - l > 1) { int mid = l + r >> 1; bool ok = true; for (int i = 0, j = mid; i < mid; ++i) { while (j < n && x[j] - x[i] < z) { j ++; } if (j == n) { ok = false; break; } j ++; } if (ok) { l = mid; } else { r = mid; } } cout << l << '\n'; }