Problem A - twiblr

直接输出 AtCoder Beginner Contest 182 Person Editorial - 图1

Problem B - Almost GCD

这里暴力枚举即可

  1. int main() {
  2. ios_base::sync_with_stdio(false), cin.tie(0);
  3. int N;
  4. cin >> N;
  5. vector<int> A(N);
  6. for (int i = 0; i < N; ++i) cin >> A[i];
  7. int Max = 0, idx = -1;
  8. for (int i = 2; i <= 1000; ++i) {
  9. int cnt = 0;
  10. for (int j = 0; j < N; ++j)
  11. if (A[j] % i == 0) cnt++;
  12. if (Max < cnt) Max = cnt, idx = i;
  13. }
  14. cout << idx << '\n';
  15. return 0;
  16. }

Problem C - To 3

利用一个数能被 AtCoder Beginner Contest 182 Person Editorial - 图2 整除当且仅当其各位之和能被 AtCoder Beginner Contest 182 Person Editorial - 图3 整除。

  • 如果本身能被 AtCoder Beginner Contest 182 Person Editorial - 图4 整除,则不需要删除。
  • 如果被 AtCoder Beginner Contest 182 Person Editorial - 图5 除余 AtCoder Beginner Contest 182 Person Editorial - 图6,则首先看是否能删去 AtCoder Beginner Contest 182 Person Editorial - 图7AtCoder Beginner Contest 182 Person Editorial - 图8,然后看是否能删去 AtCoder Beginner Contest 182 Person Editorial - 图9AtCoder Beginner Contest 182 Person Editorial - 图10
  • 如果被 AtCoder Beginner Contest 182 Person Editorial - 图11 除余 AtCoder Beginner Contest 182 Person Editorial - 图12,则首先看是否能删去 AtCoder Beginner Contest 182 Person Editorial - 图13AtCoder Beginner Contest 182 Person Editorial - 图14,然后看是否能删去 AtCoder Beginner Contest 182 Person Editorial - 图15AtCoder Beginner Contest 182 Person Editorial - 图16

C++ 代码

  1. int main() {
  2. ios_base::sync_with_stdio(false), cin.tie(0);
  3. string s;
  4. cin >> s;
  5. int cnt[3] = {0};
  6. for (int i = 0; i < s.length(); ++i) cnt[(s[i] - '0') % 3]++;
  7. int cur = (cnt[1] + 2 * cnt[2]) % 3;
  8. int k = cnt[0] + cnt[1] + cnt[2];
  9. int res;
  10. if (!cur) res = 0;
  11. else if (cur == 1) {
  12. if (cnt[1])
  13. if (k == 1) res = -1;
  14. else
  15. res = 1;
  16. else {
  17. if (k == 2) res = -1;
  18. else
  19. res = 2;
  20. }
  21. } else {
  22. if (cnt[2]) {
  23. if (k == 1) res = -1;
  24. else
  25. res = 1;
  26. } else {
  27. if (k == 2) res = -1;
  28. else
  29. res = 2;
  30. }
  31. }
  32. cout << res << "\n";
  33. return 0;
  34. }

Python 代码

  1. s = input()
  2. n = int(s)
  3. if n % 3 == 0:
  4. print(0)
  5. else:
  6. a = list(map(int, list(s)))
  7. c = [0] * 3
  8. for i in a:
  9. c[i % 3] += 1
  10. if c[n % 3] >= 1 and len(a) > 1:
  11. print(1)
  12. elif c[3 - n % 3] >= 2 and len(a) > 2:
  13. print(2)
  14. else:
  15. print(-1)

Problem D - Wandering

记录最远位置 AtCoder Beginner Contest 182 Person Editorial - 图17,当前位置 AtCoder Beginner Contest 182 Person Editorial - 图18,前缀和 AtCoder Beginner Contest 182 Person Editorial - 图19,以及前缀和的最大值 AtCoder Beginner Contest 182 Person Editorial - 图20

在每一轮中,首先更新前缀和,然后更新前缀和的最大值,本轮能达到的最大值显然是 AtCoder Beginner Contest 182 Person Editorial - 图21,用其更新 AtCoder Beginner Contest 182 Person Editorial - 图22,再用 AtCoder Beginner Contest 182 Person Editorial - 图23 更新 AtCoder Beginner Contest 182 Person Editorial - 图24

时间复杂度 AtCoder Beginner Contest 182 Person Editorial - 图25#card=math&code=%5Cmathcal%7BO%7D%28N%29)。

  1. using ll = long long;
  2. int main() {
  3. ios_base::sync_with_stdio(false), cin.tie(0);
  4. int n;
  5. cin >> n;
  6. ll a, sum = 0, hi = 0, ans = 0, pos = 0;
  7. for (int i = 0; i < n; ++i) {
  8. cin >> a;
  9. sum += a;
  10. hi = max(hi, sum);
  11. ans = max(ans, pos + hi);
  12. pos += sum;
  13. }
  14. cout << ans << "\n";
  15. return 0;
  16. }

Problem E - Akari

将所有灯和墙都放到矩形中,然后逐行从左到右扫描一遍,再从右到左扫描一遍;逐列从上到下扫描一遍,再从下到上扫描一遍。最后统计亮着的格子即可。

时间复杂度 AtCoder Beginner Contest 182 Person Editorial - 图26#card=math&code=%5Cmathcal%7BO%7D%28HW%29)。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. using ll = long long;
  4. int e[1510][1510];
  5. bool vis[1510][1510];
  6. int cnt = 0;
  7. struct node {
  8. int x, y;
  9. };
  10. int main() {
  11. ios_base::sync_with_stdio(false), cin.tie(0);
  12. int h, w, n, m;
  13. cin >> h >> w >> n >> m;
  14. vector<node> bulbs(n);
  15. for (int i = 0; i < n; ++i) {
  16. int x, y;
  17. cin >> x >> y, e[x][y] = 1; // bulb
  18. bulbs[i].x = x, bulbs[i].y = y;
  19. }
  20. for (int i = 0; i < m; ++i) {
  21. int x, y;
  22. cin >> x >> y, e[x][y] = 2; // block
  23. }
  24. for (int i = 0; i < n; ++i) {
  25. int x = bulbs[i].x, y = bulbs[i].y;
  26. if (vis[x][y] == false) {
  27. cnt++, vis[x][y] = true;
  28. }
  29. while ((e[x][y] == 0 || (x == bulbs[i].x and y == bulbs[i].y)) &&
  30. x > 0 && x <= h && y > 0 && y <= w) {
  31. if (vis[x][y] == false) cnt++, vis[x][y] = true;
  32. x++;
  33. }
  34. x = bulbs[i].x, y = bulbs[i].y;
  35. while ((e[x][y] == 0 || (x == bulbs[i].x and y == bulbs[i].y)) &&
  36. x > 0 && x <= h && y > 0 && y <= w) {
  37. if (vis[x][y] == false) cnt++, vis[x][y] = true;
  38. x--;
  39. }
  40. x = bulbs[i].x, y = bulbs[i].y;
  41. while ((e[x][y] == 0 || (x == bulbs[i].x and y == bulbs[i].y)) &&
  42. x > 0 && x <= h && y > 0 && y <= w) {
  43. if (vis[x][y] == false) cnt++, vis[x][y] = true;
  44. y--;
  45. }
  46. x = bulbs[i].x, y = bulbs[i].y;
  47. while ((e[x][y] == 0 || (x == bulbs[i].x and y == bulbs[i].y)) &&
  48. x > 0 && x <= h && y > 0 && y <= w) {
  49. if (vis[x][y] == false) cnt++, vis[x][y] = true;
  50. y++;
  51. }
  52. }
  53. cout << cnt << '\n';
  54. return 0;
  55. }

Problem F - Valid payments

dalao 题解,Orz…

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. using ll = long long;
  4. const int N = 52;
  5. ll a[N], mx[N], xx[N], dp[N][2];
  6. int main() {
  7. ios_base::sync_with_stdio(false), cin.tie(0);
  8. int n;
  9. ll x, t;
  10. cin >> n >> x;
  11. for (int i = 1; i <= n; ++i) cin >> a[i];
  12. for (int i = 1; i < n; ++i) mx[i] = a[i + 1] / a[i];
  13. t = x;
  14. for (int i = n; i; --i) {
  15. xx[i] = t / a[i];
  16. t %= a[i];
  17. }
  18. dp[1][0] = 1;
  19. if (xx[1]) dp[1][1] = 1;
  20. for (int i = 1; i < n; ++i) {
  21. dp[i + 1][0] = dp[i][0];
  22. if (xx[i + 1]) dp[i + 1][1] = dp[i][0];
  23. dp[i + 1][1] += dp[i][1];
  24. if (xx[i + 1] + 1 != mx[i + 1]) dp[i + 1][0] += dp[i][1];
  25. }
  26. cout << dp[n][0] << '\n';
  27. return 0;
  28. }

这道题,我们实际上就是要求出满足

AtCoder Beginner Contest 182 Person Editorial - 图27

并且满足

AtCoder Beginner Contest 182 Person Editorial - 图28

的整数元组 AtCoder Beginner Contest 182 Person Editorial - 图29的种数。

我们不妨从小到大进行选择。容易看到,我们其实只需要记录当前每一个可能达到的总数以及对应的方法数,而不需要记录对应的具体方案。因为AtCoder Beginner Contest 182 Person Editorial - 图30总是AtCoder Beginner Contest 182 Person Editorial - 图31的倍数,所以在选择完AtCoder Beginner Contest 182 Person Editorial - 图32的系数kiki后,我们需要保证此时的总数能够被![](https://g.yuque.com/gr/latex?a%7Bi%2B1%7D#card=math&code=a%7Bi%2B1%7D)整除。同时,因为![](https://g.yuque.com/gr/latex?%7Ck_ia_i%7C%20%3C%20a%7Bi%2B1%7D#card=math&code=%7Ckia_i%7C%20%3C%20a%7Bi%2B1%7D)的限制,因此,对于每一个原有的状态,我们实际上只能有两种选择。

我们以AtCoder Beginner Contest 182 Person Editorial - 图33作为初始状态开始递推。看起来,状态数会以指数规模增长,但实际上,任意时刻,我们最多同时保留两个状态,因此总时间复杂度为 AtCoder Beginner Contest 182 Person Editorial - 图34#card=math&code=%5Cmathcal%7BO%7D%28N%29)。

  1. using ll = long long;
  2. int main() {
  3. int n;
  4. ll x;
  5. cin >> n >> x;
  6. vector<ll> a(n);
  7. for (int i = 0; i < n; ++i) cin >> a[i];
  8. unordered_map<ll, ll> v;
  9. v[x] = 1;
  10. ll ans = 0;
  11. for (int i = 0; i < n; ++i) {
  12. unordered_map<ll, ll> nv;
  13. for (auto [c, f] : v) {
  14. if (i + 1 < n) {
  15. ll rem = c % a[i + 1];
  16. nv[c - rem] += f;
  17. if (rem > 0) nv[c + a[i + 1] - rem] += f;
  18. } else if (c % a[i] == 0)
  19. nv[0] += f;
  20. }
  21. v = move(nv);
  22. }
  23. cout << v[0];
  24. }