module IntWeightedDirectedGraphByArray = struct
  type 'a church_list = { fold : 'b. ('a -> 'b -> 'b) -> 'b -> 'b }

  (* 辺の重さがごく小さい場合は，Mapをキュー代わりに使うより配列を使った方が効率的
     時間計算量はO(E+VW)，空間計算量はO(E+W) *)
  let dijkstra_special :
    (* 頂点数n *)
    int ->
    (* 辺の重さの上限W *)
    int ->
    (* 頂点uを受け取って，
       uから伸びる辺の終点vと重さwの組みのリストを返す関数
       辺の重さwはW以下でなくてはならない *)
    (int -> (int * int) church_list) ->
    (* 始点 *)
    int ->
    (* 始点から辿り着けなければinfを返す関数
       この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
    (int -> int)
  = fun n mw es s ->
    (* 各頂点への最短距離を格納するやつ *)
    let d = Array.make n max_int in
    (* キュー *)
    let q = Array.make (mw + 1) [] in
    (* ヒープの最小要素の重み *)
    let w = ref 0 in
    (* ヒープの最小要素がどのインデックスに対応するか *)
    let i = ref 0 in
    (* ヒープに格納されている要素の数 *)
    let m = ref 1 in
    d.(s) <- 0;
    q.(0) <- [s];
    let rec dijkstra_aux t =
      (* 既に終点までの距離が分かっているので返す *)
      if !m <= 0 || d.(t) <= !w then d.(t) else
      match q.(!i) with
      (* ヒープには重さがwの要素は無かった *)
      | [] ->
          incr w;
          incr i;
          if mw < !i then i := 0;
          dijkstra_aux t
      (* ヒープには重さwの要素uが存在する *)
      | u :: us ->
          (* ヒープから重さwの要素を削除する *)
          q.(!i) <- us;
          decr m;
          if !w <= d.(u) then
            (* 未だ頂点uを訪れていない *)
            (es u).fold (fun (v, c) () ->
              if !w + c < d.(v) then begin
                d.(v) <- !w + c; (* 頂点vの重さを緩和 *)
                (* ヒープにvを追加する *)
                incr m;
                let j = !i + c - if !i + c <= mw then 0 else mw + 1 in
                q.(j) <- v :: q.(j)
              end) ();
          dijkstra_aux t in
    dijkstra_aux
end

let () = Scanf.scanf "%d" @@ fun k ->
  Printf.printf "%d\n" @@
  succ @@
  IntWeightedDirectedGraphByArray.dijkstra_special k 1 (fun i ->
    { IntWeightedDirectedGraphByArray.fold = fun f acc -> f ((i + 1) mod k, 1) @@ f (i * 10 mod k, 0) acc }) 1 0
