壊れた段をよけて階段を上る方法の数

  • 動的計画法
  • 問題 15
  • やや難しい
  • 目安 45 分

1 段、2 段、3 段ずつ上れる階段で、壊れた段を踏まずに上までたどり着く上り方の数を求める。前の段の答えを使って次の段の答えを作る、動的計画法の練習です。

本番の試験は PC で受けることが多いので、PC での練習をすすめます。スマホでも、読んで、書いて、採点するところまで動きます。

入力は標準入力から読み、答えは標準出力に書きます。1 テストあたり 3 秒までです。

問題

工場の点検で、N 段の非常階段を上ります。地面を 0 段目、いちばん上を N 段目とします。1 回の動きで、1 段、2 段、3 段のどれかだけ上ることができます。ただし、途中の M 個の段は壊れていて、踏むことができません。

0 段目から N 段目までちょうどたどり着く上り方は、何通りあるでしょうか。動きの順番が違えば、別の上り方として数えます。答えはとても大きくなることがあるので、1000000007 (10^9 + 7) で割った余りを出力してください。上り方が 1 つもないときは 0 を出力します。

入力の形式

N M
b_1
b_2
...
b_M

1 行目に段の数 N と壊れた段の数 M が半角の空白 1 つで区切られて並びます。続く M 行に、壊れた段の番号 b_i が 1 行に 1 つずつ、小さい順に並びます。M が 0 のときは、1 行目だけです。

出力の形式

上り方の数を 1000000007 で割った余りを 1 行で出力します。

制約

  • N は 1 以上 1000000 以下の整数です
  • M は 0 以上 100000 以下で、N - 1 以下の整数です
  • b_i は 1 以上 N - 1 以下の整数で、b_1 < b_2 < ... < b_M を満たします (地面と、いちばん上の段は壊れていません)

入力と出力の例

例 1

5 段の階段で、3 段目が壊れています。上り方は (1, 1, 2, 1)、(1, 1, 3)、(2, 2, 1)、(1, 3, 1)、(2, 3) の 5 通りです。たとえば (1, 2, 2) は 3 段目を踏むので数えません。

入力

5 1
3

出力

5

例 2

4 段の階段で、壊れた段はありません。上り方は 7 通りです。

入力

4 0

出力

7

ヒント

まだ開いていません

付箋は 3 枚。下の段ほど答えに近づきます

  1. ヒント 2

  2. ヒント 3答えに近い

main.py
import sys

MOD = 10**9 + 7

data = sys.stdin.read().split()
n, m = int(data[0]), int(data[1])
broken_steps = [int(data[2 + i]) for i in range(m)]

# ここから書く

入力

出力

「実行する」を押すと、ここに出力が出ます

できているか「提出して採点」を押すと、隠れたテストを全部走らせて、通ったかをここに出します