Powered by AppSignal & Oban Pro

ABC042D - いろはちゃんとマス目

submit_1.livemd

ABC042D - いろはちゃんとマス目

問題

https://atcoder.jp/contests/abc042/tasks/arc058_b

回答1

defmodule Combination do
  @mod 1_000_000_007
  @max_index 200_000

  defp renew_table(table_name, initial_objects) do
    if :ets.info(table_name) != :undefined do
      :ets.delete(table_name)
    end

    :ets.new(table_name, [:set, :protected, :named_table])
    :ets.insert(table_name, initial_objects)
  end

  defp lookup(table_name, key) do
    [{_, value}] = :ets.lookup(table_name, key)
    value
  end

  def init do
    renew_table(:factorial, [{0, 1}, {1, 1}])
    renew_table(:inverse, [{1, 1}])
    renew_table(:factorial_inverse, [{0, 1}, {1, 1}])

    2..@max_index
    |> Enum.reduce(1, fn index, acc ->
      factorial = rem(acc * index, @mod)

      mod_inverse = lookup(:inverse, rem(@mod, index))
      inverse = @mod - rem(mod_inverse * div(@mod, index), @mod)

      pre_factorial_inverse = lookup(:factorial_inverse, index - 1)
      factorial_inverse = rem(pre_factorial_inverse * inverse, @mod)

      :ets.insert(:factorial, {index, factorial})
      :ets.insert(:inverse, {index, inverse})
      :ets.insert(:factorial_inverse, {index, factorial_inverse})

      factorial
    end)
  end

  def combination(n, r) do
    factorial_n = lookup(:factorial, n)
    factorial_inverse_nr = lookup(:factorial_inverse, n - r)
    factorial_inverse_r = lookup(:factorial_inverse, r)

    (factorial_inverse_nr * factorial_inverse_r)
    |> rem(@mod)
    |> Kernel.*(factorial_n)
    |> rem(@mod)
  end
end
Combination.init()
Combination.combination(6, 4)
defmodule Main do
  def main do
    :stdio
    |> IO.read(:all)
    |> solve()
    |> IO.puts()
  end

  defp split_words(words) do
    String.split(words, " ")
  end

  def solve(input) do
    [h, w, a, b] =
      input
      |> String.trim()
      |> split_words()
      |> Enum.map(&String.to_integer/1)

    Combination.init()

    0..(h - a - 1)
    |> Enum.reduce(0, fn h_i, acc ->
      l = Combination.combination(h_i + b - 1, h_i)
      r = Combination.combination(h + w - h_i - b - 2, h - 1 - h_i)
      acc + l * r
    end)
    |> rem(1_000_000_007)
  end
end
"""
2 3 1 1
"""
|> Main.solve()
|> then(&(&1 == 2))
"""
10 7 3 4
"""
|> Main.solve()
|> then(&(&1 == 3570))
"""
100000 100000 99999 99999
"""
|> Main.solve()
|> then(&(&1 == 1))
"""
100000 100000 44444 55555
"""
|> Main.solve()
|> then(&(&1 == 738_162_020))