Contest 3/14
A:ARC112A
可以发现答案是一个等差数列,注意2L>R的时答案是0。
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; int m = 2000000; vector<long long> ans(m + 1); for (int i = 1; i <= m; ++i) { ans[i] = ans[i - 1] + i; } while (T --) { long long l, r; cin >> l >> r; if (l + l <= r) { cout << ans[r - l - l + 1] << '\n'; } else { cout << 0 << '\n'; } } return 0; }
可以发现尽量均匀地放是最优的,那么从小到大枚举mex,计算这个mex有多少个对于答案的贡献即可。
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, k; cin >> n >> k; vector<int> a(n); for (int i = 0; i < n; ++i) { cin >> a[i]; } vector<int> cnt(n + 1); for (int i = 0; i < n; ++i) { cnt[a[i]] ++; } int cur = k; long long ans = 0; for (int i = 0; i <= n; ++i) { ans += 1LL * max(0, cur - cnt[i]) * i; cur = min(cur, cnt[i]); } cout << ans << '\n'; return 0; }
C:Codeforces1208C
观察到当N为4的倍数时,N^(N+3)=(N+1)^(N+2)=3,所以把网格分成四个四个的小格子,每个小格子填上N,N+1,N+2,N+3即可。
#include <bits/stdc++.h> using namespace std; int main() { int N; cin >> N; vector<vector<int>> A(N, vector<int> (N)); int X = 0; for (int i = 0; i < N; i += 2) { for (int j = 0; j < N; j += 2) { A[i][j] = X; A[i][j + 1] = X + 1; A[i + 1][j] = X + 2; A[i + 1][j + 1] = X + 3; X += 4; } } for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { cout << A[i][j] << " \n"[j == N - 1]; } } return 0; }
D:GYM102920E
dp[i][0/1][0/1]表示到了第i个位置,之前的两局的胜负情况分别是0/1和0/1,转移枚举当前的两局的胜负情况即可。
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector<int> P(N); for (int i = 0; i < N; ++i) { cin >> P[i]; } vector<vector<vector<int>>> dp(N + 1, vector<vector<int>> (2, vector<int> (2))); dp[0][0][0] = 1; for (int i = 0; i < N - 1; ++i) { for (int a = 0; a < 2; ++a) { for (int b = 0; b < 2; ++b) { for (int c = 0; c < 2; ++c) { for (int d = 0; d < 2; ++d) { if (abs(a + c - b - d) == P[i]) { dp[i + 1][c][d] |= dp[i][a][b]; } } } } } } bool ok = false; for (int a = 0; a < 2; ++a) { for (int b = 0; b < 2; ++b) { if (dp[N - 1][a][b] && abs(a - b) == P[N - 1]) { ok = true; } } } if (ok) { cout << "YES" << '\n'; } else { cout << "NO" << '\n'; } return 0; };
E:Codeforces1023E
一个比较自然的想法是每次询问下一步是否能连向终点,这样分别会从起点以及终点到达对角线,但是不一定相遇。在走的时候从起点出发时贪心地尽量向下走,从终点出发时尽量向左走,这样最终肯定会相遇。
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; auto query = [&] (int r1, int c1, int r2, int c2) -> bool { cout << '?' << ' ' << r1 + 1 << ' ' << c1 + 1 << ' ' << r2 + 1 << ' ' << c2 + 1 << endl; string ret; cin >> ret; if (ret == "YES") { return true; } else { return false; } }; auto dis = [&] (int r1, int c1, int r2, int c2) -> int { return abs(r1 - r2) + abs(c1 - c2); }; int x = 0; int y = 0; vector<pair<int, int> > path; path.emplace_back(0, 0); while (dis(0, 0, x, y) < n - 1) { if (query(x + 1, y, n - 1, n - 1)) { x ++; } else { y ++; } path.emplace_back(x, y); } int m = path.size(); x = n - 1; y = n - 1; vector<pair<int, int> > b; b.emplace_back(n - 1, n - 1); for (int i = m - 2; i >= 0; --i) { if (query(0, 0, x, y - 1)) { y --; } else { x --; } b.emplace_back(x, y); } b.pop_back(); while (!b.empty()) { path.push_back(b.back()); b.pop_back(); } cout << '!' << ' '; for (int i = 0; i + 1 < path.size(); ++i) { if (path[i].first != path[i + 1].first) { cout << 'D'; } else { cout << 'R'; } } cout << endl; return 0; }