AtCoder参戦日記 ABC180 2020/11/01
2020/11/01にバーチャル参加したABC180の記録です。日程的に参加できなかったコンテストに後日バーチャル参加しました。
55分ぐらいで4完でした。終了後5分ぐらいで5問目ができました。
問題 | 結果 | 言語 |
---|---|---|
A | ○ | Ruby |
B | ○ | Scala |
C | ○ | C++ |
D | ○ | Java |
E | 競技後にJava | |
F |
- A - box
- B - Various distances
- C - Cream puff
- D - Takahashi Unevolved
- E - Traveling Salesman among Aerial Cities
過去の参戦記録
参加日 | # | コンテスト名 | 結果 | 使用言語 |
---|---|---|---|---|
2020/08/29 | #1 | ABC177 | 3完 | Scala, Scala, Java |
2020/09/13 | #2 | ABC178 | 5完 | Python, Scala, Scala, C++, Scala |
2020/09/19 | #3 | ABC179 | 3完 | Java, Scala, Scala |
2020/10/03 | #4 | ARC104 | 2完 | Python, Scala |
2020/10/10 | #5 | HHKB2020 | 3完 | C++, Scala, Java |
2020/10/11 | #6 | ARC105 | 2完 | Ruby, Java |
2020/11/01 | ABC180 | 4完 | Ruby, Scala, C++, Java |
A - box
簡単な問題なのでRubyで解きました。
n, a, b = gets.strip.split(" ").map(&:to_i) puts(n - a + b)
B - Various distances
ロジック的に書きやすいScalaで解きました。
object Main extends App { val sc = new java.util.Scanner(System.in); val n = sc.nextInt(); val xs = Array.fill(n)(sc.nextInt()); val r1 = xs.map(x => (x max (-x)).toLong).sum; val r2 = Math.sqrt(xs.map(x => x.toLong * x).sum); val r3 = xs.map(x => (x max (-x)).toLong).max; println(r1); println(r2); println(r3); }
C - Cream puff
nの平方根を上限にループを回せばよいことまではわかりますが、それ以上の効率化が思いつかず、処理速度がネックになる可能性がわからなかったので、最速のC++で書きました。
#include <bits/stdc++.h> using namespace std; int main() { long n; cin >> n; int n2 = (int)sqrt((double)n); vector<int> vec = {}; int last = 0; for (int i = 1; i <= n2; i++) { if (n % i == 0) { cout << i << endl; vec.push_back(i); last = i; } } for (int i = vec.size() - 1; i >= 0; i--) { long i2 = n / vec.at(i); if (i2 != last) { cout << i2 << endl; } } }
D - Takahashi Unevolved
対数の計算が含まれる解法です。最初は浮動小数点数で対数を計算しましたが、WAになってしまいましたので、整数での計算に改良してACを取りました。言語はこのロジックを書きやすそうなJavaになりました。
以下は競技終了後にさらに少し改善したコードです。
import java.util.Scanner; class Main { public static long log(long a, long max) { long acc = 0; while (true) { if (max < a) { return acc; } int n = 1; long s = a; while (true) { long s2 = s * s; if (s2 > max) break; s = s2; n <<= 1; } max = max / s; acc = acc + n; } } public static long pow(long a, long n) { long s = 1; while (n > 0) { if ((n & 1) != 0) s = s * a; a = a * a; n >>= 1; } return s; } public static void main(String[] args) { var sc = new Scanner(System.in); long x = sc.nextLong(); long y = sc.nextLong(); long a = sc.nextLong(); long b = sc.nextLong(); long th = b / (a - 1); if (th >= y) th = y - 1; long na = log(a, th / x); long x2 = x * pow(a, na); long nb = (y - x2 - 1) / b; long answer = na + nb; System.out.println(answer); } }
E - Traveling Salesman among Aerial Cities
競技中40分考えて、コード書き途中で終わってしまいました。競技終了後5分ぐらいでAC取れました。前問に続き、このロジックを書きやすそうなJavaになりました。
import java.util.Scanner; class Main { private static int cost(int[] x, int[] y, int[] z, int k, int j) { if (j == 16) j = 0; else j = j + 1; if (k == 16) k = 0; else k = k + 1; int rx = x[j] - x[k]; int ry = y[j] - y[k]; int rz = z[j] - z[k]; if (rx < 0) rx = -rx; if (ry < 0) ry = -ry; if (rz < 0) rz = 0; return rx + ry + rz; } public static void main(String[] args) { var sc = new Scanner(System.in); int n = sc.nextInt(); var x = new int[n]; var y = new int[n]; var z = new int[n]; for (int i = 0; i < n; i++) { x[i] = sc.nextInt(); y[i] = sc.nextInt(); z[i] = sc.nextInt(); } var dp = new int[(1 << 16) * 16]; int i_max = (1 << (n-1)) - 1; for (int i = 0; i <= i_max; i++) { for (int j = 0; j < 16; j++) { if ((i & (1 << j)) == 0) continue; int i2 = i ^ (1 << j); int cost = Integer.MAX_VALUE; for (int k = 0; k < 16; k++) { if ((i2 & (1 << k)) == 0) continue; int c = dp[i2 * 16 + k] + cost(x, y, z, k, j); if (c < cost) cost = c; } if (cost == Integer.MAX_VALUE) { cost = cost(x, y, z, 16, j); } dp[i * 16 + j] = cost; } } int cost = Integer.MAX_VALUE; for (int j = 0; j < (n-1); j++) { if ((i_max & (1 << j)) == 0) continue; int c = dp[i_max * 16 + j] + cost(x, y, z, j, 16); if (c < cost) cost = c; } System.out.println(cost); } }