2021暑假模拟赛10
A[CF1497A(800)]
可以发现从小到大排序后$mex$最大,于是排序后统计即可。
#include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; while (T --) { int N; cin >> N; vector<int> A(N); for (int i = 0; i < N; ++i) { cin >> A[i]; } vector<int> cnt(101); for (int i = 0; i < N; ++i) { cnt[A[i]] ++; } vector<int> Ans; for (int i = 0; i < 101; ++i) { if (cnt[i] > 0) { cnt[i] --; Ans.push_back(i); } } for (int i = 0; i < 101; ++i) { for (int j = 0; j < cnt[i]; ++j) { Ans.push_back(i); } } for (int i = 0; i < N; ++i) { cout << Ans[i] << " \n"[i == N - 1]; } } return 0; }
B[CF1086B(1700)]
发现本质上直径肯定存在于两个叶子的路径上,于是把权值均匀地分布在叶子上可以使得答案最小。
#include <bits/stdc++.h> using namespace std; int main() { int N, S; cin >> N >> S; vector<vector<int>> adj(N); vector<int> d(N); for (int i = 0; i < N - 1; ++i) { int X, Y; cin >> X >> Y; X --; Y --; d[X] ++; d[Y] ++; } int D = 0; for (int i = 0; i < N; ++i) { if (d[i] == 1) { D ++; } } cout << fixed << setprecision(15); cout << ((long double)S / (long double)D * 2.) << '\n'; return 0; }
C[GYM103102D(1600)]
考虑一个区间$dp$,$dp[l][r]$表示区间$[l,r]$能获得的最大价值,转移枚举分割点即可。合并两个区间的代价预处理区间乘积即可。
#include <bits/stdc++.h> using namespace std; const int P = 1000003; int main() { int N; cin >> N; vector<int> A(N); for (int i = 0; i < N; ++i) { cin >> A[i]; } vector<vector<long long>> Mul(N, vector<long long> (N)); for (int i = 0; i < N; ++i) { Mul[i][i] = A[i]; for (int j = i; j + 1 < N; ++j) { Mul[i][j + 1] = 1LL * Mul[i][j] * A[j + 1] % P; } } vector<vector<long long>> dp(N, vector<long long> (N)); for (int L = 1; L < N; ++L) { for (int i = 0; i + L < N; ++i) { int j = i + L; for (int k = i; k < j; ++k) { dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j] + (Mul[i][k] - Mul[k + 1][j]) * (Mul[i][k] - Mul[k + 1][j])); } } } cout << dp[0][N - 1] << '\n'; }
D[CF1497E1(1700)]
首先可以发现一个贪心,尽量把元素塞进当前区间,塞不进去开新的一段。那么问题在于如何判断塞进当前元素后是否合法,这里只需要判断是否存在完全平方数即可,那么等价于是否存在一个质因子的指数不为$0$且为偶数次。于是每次把元素暴力质因子分解,用$map$存储之前的质因子,判断即可。
#include <bits/stdc++.h> using namespace std; vector<int> GetPrime(int n) { vector<bool> mark(n + 1); vector<int> Prime; for (int i = 2; i <= n; ++i) { if (!mark[i]) { Prime.emplace_back(i); } for (int j = 0; j < Prime.size() && i * Prime[j] <= n; ++j) { mark[i * Prime[j]] = true; if (i % Prime[j] == 0) { break; } } } return Prime; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); vector<int> P = GetPrime(10000000); int T; cin >> T; while (T --) { int N, K; cin >> N >> K; vector<int> A(N); for (int i = 0; i < N; ++i) { cin >> A[i]; } map<vector<int>, int> mp; int Ans = 0; for (int i = 0; i < N; ++i) { vector<int> F; for (int j : P) { if (j * j > A[i]) { break; } if (A[i] % j == 0) { int W = 0; while (A[i] % j == 0) { A[i] /= j; W ^= 1; } if (W == 1) { F.push_back(j); } } } if (A[i] > 1) { F.push_back(A[i]); } sort(F.begin(), F.end()); if (i == 0 || mp.find(F) != mp.end()) { mp.clear(); Ans ++; } mp[F] = 1; } cout << Ans << '\n'; } return 0; }