1
1

More than 1 year has passed since last update.

AtCoder ABC310 解法(A ~ E) Ruby & Kotlin

Posted at

解法

A - Order Something Else

公式解説
Difficulty Solve Prob Solve Time
23 > 99 % 4 mins

Ruby

abc310_a.rb
N, P, Q = gets.split.map(&:to_i)
D = gets.split.map(&:to_i)
puts [D.min + Q, P].min

Kotlin

abc310_a.kt
fun main() {
  val (N, P, Q) = readLine()!!.split(" ").map(String::toInt)
  val D = readLine()!!.split(" ").map(String::toInt)
  println(Math.min(P, D.min()!! + Q))
}

B - Strictly Superior

公式解説
Difficulty Solve Prob Solve Time
226 96 % 19 mins

Ruby

abc310_b.rb
N, M = gets.split.map(&:to_i)
# あらかじめjの候補を昇順で並び替えて置く
# Pi >= Pj && Ci <= Cj となる順
PCF = Array.new(N) { gets.split.map(&:to_i) }.sort_by { [_1[0], -_1[1]] }

N.times do |j|
  (j + 1).upto(N - 1) do |i|
    pj, cj, *fj = PCF[j]
    pi, ci, *fi = PCF[i]
    # fiとfjの和集合の数がfjの数を超える場合、上位互換になり得ない
    next if (fi | fj).size > cj
    if pi > pj || ci < cj
      puts "Yes"
      exit
    end
  end
end
puts "No"

Kotlin

abc310_b.kt
fun main() {
  val (N, M) = readLine()!!.split(" ").map(String::toInt)
  val PCF = MutableList(N) { readLine()!!.split(" ").map(String::toInt) }

  // あらかじめjの候補を昇順で並び替えて置く
  // Pi >= Pj && Ci <= Cj となる順
  PCF.sortWith(compareBy({ it[0] }, { - it[1] }))

  for (j in 0 .. N - 2) {
    for (i in j + 1 .. N - 1) {
      val pj = PCF[j][0]
      val cj = PCF[j][1]
      val fj = PCF[j].subList(2, PCF[j].size).toSet()
      val pi = PCF[i][0]
      val ci = PCF[i][1]
      val fi = PCF[i].subList(2, PCF[i].size).toSet()

      // fiとfjの和集合の数がfjの数を超える場合、上位互換になり得ない
      if (fj.union(fi).size > cj) continue
      if (pi > pj || ci < cj) {
        println("Yes")
        return
      }
    }
  }
  println("No")
}

C - Reversible

公式解説
Difficulty Solve Prob Solve Time
272 95 % 11 mins

Ruby

abc310_c.rb
require "set"
N = gets.to_i

set = Set.new
N.times do |i|
  s = gets.chomp
  # 前後反転した文字列と元の文字列を配列で並べ、
  # ソートした後に文字列にする。
  # これにより、"abc"と"cba"を同一とみなせる。
  set << [s, s.reverse].sort.join
end

puts set.size

Kotlin

abc310_c.kt
fun main() {
  val N = readLine()!!.toInt()
  val S = mutableSetOf<String>()

  repeat(N) {
    val s = readLine()!!
    // 前後反転した文字列と元の文字列を配列で並べ、
    // ソートした後に文字列にする。
    // これにより、"abc"と"cba"を同一とみなせる。
    S.add(listOf(s, s.reversed()).sorted().joinToString(""))
  }
  println(S.size)
}

D - Peaceful Teams

公式解説

深さ優先探索(DFS)

Difficulty Solve Prob Solve Time
1368 11 % 38 mins

Ruby

abc310_d.rb
N, T, M = gets.split.map(&:to_i)
HATE = Array.new(N + 1) { [] }

M.times do
  a, b = gets.split.map(&:to_i).map(&:pred)
  HATE[a] << b
  HATE[b] << a
end

# i 番目の選手(0 <= i < N)
# teamsは各チームの配列の配列
def dfs(i, teams)
  if i == N
    # チーム数がTとなっていた場合条件を満たすためカウント
    return teams.size == T ? 1 : 0
  end
  cnt = 0

  # 既存チームにi番目の選手を追加する場合
  teams.each_with_index do |t, j|
    # tの選手の中にi番目の選手と相性が悪い選手がいた場合は除外
    next if (t & HATE[i]).size > 0
    teams_copy = teams.map { _1.clone }
    teams_copy[j] << i
    cnt += dfs(i + 1, teams_copy)
  end

  # 新たなチームを作りi番目の選手を追加する場合
  cnt += dfs(i + 1, teams + [[i]]) if teams.size < T
  cnt
end

puts dfs(1, [[0]])

Kotlin

abc310_d.kt
fun main() {
  // kotlinでは再帰DFSはすぐにスタックオーバーフローするので記述
  // この問題ではこの方法を使用しなくてもACできる
  Thread(null, ::solve, "solve", 1.shl(26)).start()
}

fun solve() {
  val (N, T, M) = readLine()!!.split(" ").map(String::toInt)
  val HATE = MutableList(N) { mutableListOf<Int>() }
  repeat(M) {
    val (a, b) = readLine()!!.split(" ").map(String::toInt)
    HATE[a - 1].add(b - 1)
    HATE[b - 1].add(a - 1)
  }

  /**
   * i 選手の番号(0 <= i < N)
   * teams チームの配列の配列
   * 場合の数
   */
  fun dfs(i: Int, teams: MutableList<MutableList<Int>>): Int {
    if (i == N) {
      // チーム数がTとなっていた場合条件を満たすためカウント
      return if (teams.size == T) 1 else 0
    }
    var cnt = 0

    // 既存チームにi番目の選手を追加する場合
    teams.forEachIndexed { j, team ->
      // teamの選手の中にi番目の選手と相性が悪い選手がいた場合は早期リターン
      if ((team.intersect(HATE[i])).size > 0) return@forEachIndexed
      val teamsCopy = teams.map { it.toMutableList() }.toMutableList()
      teamsCopy[j].add(i)
      cnt += dfs(i + 1, teamsCopy)
    }

    // 新たなチームを作りi番目の選手を追加する場合
    if (teams.size < T) cnt += dfs(i + 1, teams + mutableListOf(mutableListOf(i)))

    return cnt
  }

  println(dfs(1, mutableListOf(mutableListOf(0))))
}

E - NAND repeatedly

公式解説
Difficulty Solve Prob Solve Time
1261 16 % 37 mins

Ruby

abc310_e.rb
N = gets.to_i
S = gets.chomp.chars.map(&:to_i)

# f(0, j) ... f(j - 1, j)の中で、
# zero = fが0である場合の数
# one = fが1である場合の数 = f(0, j) + ... + f(j - 1, j)
ans = zero = one = 0

S.each do |i|
  if i.zero?
    # zeroとなるのは、f(i, i) = 0 ⊼ 0 の場合
    # oneとなるのは、0 ⊼ 0 と 1 ⊼ 0 の場合
    zero, one = 1, zero + one
  else
    # zeroとなるのは、1 ⊼ 1 の場合
    # oneとなるのは、0 ⊼ 1 と f(i, i) の場合
    zero, one = one, zero + 1
  end
  ans += one
end

puts ans

Kotlin

答えは$10^9$を超えるためLong型

abc310_e.kt
fun main() {
  val N = readLine()!!.toInt()
  val S = readLine()!!.toList()

  var ans = 0L
  // f(0, j) ... f(j - 1, j)の中で、
  // zero = fが0である場合の数
  // one = fが1である場合の数 = f(0, j) + ... + f(j - 1, j)
  var zeroOne = Pair(0L, 0L)

  S.forEach {
    if (it == '0') {
      // zeroとなるのは、f(i, i) = 0 ⊼ 0 の場合
      // oneとなるのは、0 ⊼ 0 と 1 ⊼ 0 の場合
      zeroOne = Pair(1L, zeroOne.first + zeroOne.second)
    } else {
      // zeroとなるのは、1 ⊼ 1 の場合
      // oneとなるのは、0 ⊼ 1 と f(i, i) の場合
      zeroOne = Pair(zeroOne.second, zeroOne.first + 1L)
    }
    ans += zeroOne.second
  }
  println(ans)
}

その他のAtCoder関連の解法コード

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1