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 Rust (1.42.0) (judge verdict: Accepted)

use proconio::input;

// max_flow {{{
#[allow(dead_code)]
mod max_flow {
    use std::{
        fmt::{Debug, Display},
        ops::{Add, AddAssign, Sub, SubAssign},
    };

    pub trait FlowTrait:
        Debug
        + Display
        + Clone
        + Copy
        + PartialOrd
        + Ord
        + Eq
        + PartialEq
        + Add
        + AddAssign
        + Sub
        + SubAssign
    {
        fn zero() -> Self;
        fn infinity() -> Self;
    }

    macro_rules! flow_value_impl_integer {
        ($($ty: ident,)*) => {
            $(impl FlowTrait for $ty {
                #[inline]
                fn zero() -> Self {
                    0
                }
                #[inline]
                fn infinity() -> Self {
                    std::$ty::MAX
                }
            })*
        };
    }

    flow_value_impl_integer! {
        usize, u8, u16, u32, u64, u128,
    }

    #[derive(Debug, Clone)]
    struct FlowEdge<Value: FlowTrait> {
        to: usize,
        cap: Value,
        rev: usize,
    }

    #[derive(Debug, Clone)]
    pub struct DoubleEdge {
        from: usize,
        from_idx: usize,
        to: usize,
        to_idx: usize,
    }

    #[derive(Debug, Clone)]
    pub struct MaxFlow<Value: FlowTrait> {
        source: usize,
        sink: usize,
        network: Vec<Vec<FlowEdge<Value>>>,
    }

    impl<Value: FlowTrait> MaxFlow<Value> {
        fn len(&self) -> usize {
            self.network.len()
        }

        pub fn with_size_source_sink(n: usize, source: usize, sink: usize) -> Self {
            Self {
                source,
                sink,
                network: vec![vec![]; n],
            }
        }

        pub fn insert(&mut self, u: usize, v: usize, cap: Value) {
            let su = self.network[u].len();
            let sv = self.network[v].len();
            self.network[u].push(FlowEdge {
                to: v,
                cap,
                rev: sv,
            });
            self.network[v].push(FlowEdge {
                to: u,
                cap: Value::zero(),
                rev: su,
            });
        }

        pub fn run(&mut self) -> Value {
            let mut flow = Value::zero();
            loop {
                // 最短距離を計算です。
                let dist = self.construct_dist_array();
                if dist[self.sink] == std::usize::MAX {
                    return flow;
                }

                // 増分路と流せる量を計算です。
                let mut path = Vec::new();
                let e = self.dfs(self.source, Value::infinity(), &dist, &mut path);
                assert_ne!(e, Value::zero());

                // 増分路をネットワークに反映させて、流せる量を答えに足します。
                for DoubleEdge {
                    from,
                    from_idx,
                    to,
                    to_idx,
                } in path
                {
                    self.network[from][from_idx].cap -= e;
                    self.network[to][to_idx].cap += e;
                }
                flow += e;
            }
        }

        fn dfs(&self, from: usize, d: Value, dist: &[usize], path: &mut Vec<DoubleEdge>) -> Value {
            if from == self.sink {
                return d;
            }
            for (from_idx, &FlowEdge { to, cap, rev }) in self.network[from]
                .iter()
                .enumerate()
                .filter(|&(_, &FlowEdge { to, cap, rev: _ })| {
                    cap != Value::zero() && dist[from] + 1 == dist[to]
                })
            {
                let e = self.dfs(to, d.min(cap), dist, path);
                if e == Value::zero() {
                    continue;
                }
                path.push(DoubleEdge {
                    from,
                    from_idx,
                    to,
                    to_idx: rev,
                });
                return e;
            }
            Value::zero()
        }

        fn construct_dist_array(&self) -> Vec<usize> {
            let mut dist = vec![std::usize::MAX; self.len()];
            dist[self.source] = 0;
            let mut queue = std::collections::VecDeque::with_capacity(self.len());
            queue.push_back(self.source);
            while let Some(from) = queue.pop_front() {
                for &FlowEdge { to, cap: _, rev: _ } in
                    self.network[from].iter().filter(|e| e.cap != Value::zero())
                {
                    if dist[to] == std::usize::MAX {
                        dist[to] = dist[from] + 1;
                        queue.push_back(to);
                    }
                }
            }
            dist
        }
    }
}
// }}}

fn main() {
    input!(n: usize, a: [i64; n]);
    let source = 0;
    let sink = n + 1;
    let mut network = max_flow::MaxFlow::with_size_source_sink(n + 2, source, sink);
    for i in 1..=n {
        let x = a[i - 1];
        if 0 < x {
            network.insert(source, i, x as u64);
        } else if x < 0 {
            network.insert(i, sink, (-x) as u64);
        }
        for j in std::iter::successors(Some(2 * i), |x| Some(x + i)).take_while(|&j| j <= n) {
            network.insert(j, i, std::u64::MAX);
        }
    }
    let flow = network.run();
    println!("{}", a.iter().map(|&x| x.max(0)).sum::<i64>() - flow as i64);
}