Problem:
Score : 700 points

Problem Statement

We have N gemstones labeled 1 through N.

You can perform the following operation any number of times (possibly zero).

Select a positive integer x, and smash all the gems labeled with multiples of x.

Then, for each i, if the gem labeled i remains without getting smashed, you will receive a_i yen (the currency of Japan).
However, a_i may be negative, in which case you will be charged money.

By optimally performing the operation, how much yen can you earn?

Constraints

All input values are integers.

1 \leq N \leq 100

|a_i| \leq 10^9

Input

Input is given from Standard Input in the following format:

N
a_1 a_2 ... a_N

Output

Print the maximum amount of money that can be earned.

Sample Input 1

6
1 2 -6 4 5 3

Sample Output 1

12

It is optimal to smash Gem 3 and 6.

Sample Input 2

6
100 -100 -100 -100 100 -100

Sample Output 2

200

Sample Input 3

5
-1 -2 -3 -4 -5

Sample Output 3

0

It is optimal to smash all the gems.

Sample Input 4

2
-1000 100000

Sample Output 4

99000

Solution in OCaml (4.02.3) (judge verdict: Accepted)

module DirectedGraph
  (* 道の表現 *)
  (Path : sig
    type t
    (* 辺の名前 *)
    type edge
    (* 長さ0の道 *)
    val nil : t
    (* 道の後ろに辺を付け足した道 *)
    val snoc : t -> edge -> t
  end) :
sig
  (* BFSにより，重みのないグラフの最短経路を求める *)
  val bfs :
    (* 頂点数（Hashtblを用いるので目安程度） *)
    int ->
    (* 辺の名前が付いた隣接リスト *)
    ('v -> ('v * Path.edge) list) ->
    (* 始点 *)
    'v ->
    (* 最短経路を返す関数 辿り着けなければNoneを返す） *)
    ('v -> Path.t option)
end = struct
  let rec bfs_aux es d frontier t =
    try Some (Hashtbl.find d t) with
    | Not_found ->
        match !frontier with
        | [] -> None
        | _ :: _ ->
            frontier := List.fold_right (fun u ->
              List.fold_right (fun (v, e) frontier ->
                if Hashtbl.mem d v
                then frontier
                else (Hashtbl.add d v (Path.snoc (Hashtbl.find d u) e); v :: frontier))
              (es u)) !frontier [];
            bfs_aux es d frontier t

  (*
   * 終点に辿り着いた時点で探索を切り上げるが，
   * 戻り値の関数を覚えておくと，途中まで探索した結果が再利用される
   * （#trace bfs_aux すると分かりやすい）
   *)
  let bfs n es s =
    let d = Hashtbl.create n in
    Hashtbl.add d s Path.nil;
    let frontier = ref [s] in
    bfs_aux es d frontier
end

module FlowNetwork
  (* 流量 *)
  (Flow : sig
    type t
    val inf : t
    val zero : t
    val ( + ) : t -> t -> t
    val ( - ) : t -> t -> t
    val compare : t -> t -> int
  end) :
sig
  val max_flow :
    (* 頂点の数（Hashtblを用いるので目安程度） *)
    int ->
    (* 始点 *)
    'v ->
    (* 終点 *)
    'v ->
    (* 各辺とその逆辺の容量 *)
    ('v * 'v * Flow.t * Flow.t) list ->
    (* 最大フロー *)
    Flow.t *
    (* 最大フローを流した際の各辺の流量 *)
    ('v * 'v * Flow.t) list
end =
struct
  module G = DirectedGraph (struct
    type t = int
    type edge = unit
    let nil = 0
    let snoc t _ = t + 1
  end)

  (* 増加パスをDFSで探し，流せるだけ流していく *)
  let rec dfs capacity add_edge iter level v t f =
    if v = t then f
    else begin
      let rec find () =
        match Hashtbl.find iter v with
        | exception Not_found -> Flow.zero
        | (u, i) ->
            Hashtbl.remove iter v;
            (* capacity i <= 0 *)
            if Flow.compare (capacity i) Flow.zero <= 0 || level u <= level v then find ()
            else begin
              let d = dfs capacity add_edge iter level u t @@
                (* min f (capacity i) *)
                if Flow.compare f (capacity i) <= 0 then f else capacity i in
              (* d <= 0 *)
              if Flow.compare d Flow.zero <= 0 then find ()
              else (add_edge i d; d)
            end in find ()
    end

  let max_flow n s t es =
    assert (s <> t);
    (* 各辺に流せる流量 *)
    let capacity = Array.make (2 * List.length es) Flow.zero in
    (* 逆辺を張りつつ，隣接リスト形式に変換 *)
    let adj = Hashtbl.create n in
    List.iteri (fun i (u, v, c, c') ->
      (* 各辺は番号で管理する *)
      Hashtbl.add adj u (v, 2 * i);
      (* 容量はcapacityを見てほしい *)
      capacity.(2 * i) <- c;
      (* 逆辺 *)
      Hashtbl.add adj v (u, 2 * i + 1);
      capacity.(2 * i + 1) <- c') es;
    (* 番号iの辺にcだけフローを流す *)
    let add_edge i c =
      let open Flow in
      capacity.(i) <- capacity.(i) - c;
      (* 逆辺 *)
      capacity.(i lxor 1) <- capacity.(i lxor 1) + c in
    let rec outer flow =
      let level = G.bfs n (fun v ->
        List.concat @@ List.map (fun (u, i) ->
          if Flow.compare capacity.(i) Flow.zero <= 0 then []
          else [(u, ())]) @@ Hashtbl.find_all adj v) s in
      if level t = None then flow
      else
        let iter = Hashtbl.copy adj in
        let rec inner flow =
          let f = dfs (fun i -> capacity.(i)) add_edge iter level s t Flow.inf in
          if Flow.compare f Flow.zero <= 0 then flow
          else inner (Flow.( + ) flow f) in
        outer @@ inner flow in
    let f = outer Flow.zero in
    (f, List.mapi (fun i (u, v, c, _) ->
      (u, v, Flow.( - ) c capacity.(2 * i))) es)
end

module G = FlowNetwork (struct
  type t = int
  let inf = max_int
  let zero = 0
  let ( + ) = ( + )
  let ( - ) = ( - )
  let compare = compare
end)

let () = Scanf.scanf "%d\n" @@ fun n ->
  let as_ = Array.to_list @@
    Array.init n @@ fun _ ->
      Scanf.scanf "%d " @@ fun a -> a in
  Printf.printf "%d\n" @@ ( - ) (List.fold_right (fun a -> ( + ) @@ max 0 a) as_ 0) @@
    fst @@ G.max_flow n 0 1 @@ List.concat @@ List.mapi (fun i a ->
      ( if a = 0 then []
        else if a < 0 then [(0, i + 2, ~- a, 0)]
        else [(i + 2, 1, a, 0)] ) @
      List.concat @@ Array.to_list @@ Array.init n @@ fun j ->
        if i < j && (j + 1) mod (i + 1) = 0 then [(i + 2, j + 2, max_int, 0)]
        else []) as_