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.15.1) (judge verdict: Accepted)

use std::io::*;
use std::str::FromStr;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

type Weight = i64;
#[allow(dead_code)]
#[derive(Clone, Debug, Eq, PartialEq)]
struct Edge {
    index: usize,
    src: usize,
    dest: usize,
    weight: Weight,
}
#[allow(dead_code)]
impl Edge {
    fn new(index: usize, src: usize, dest: usize, weight: Weight) -> Edge {
        Edge {
            index: index,
            src: src,
            dest: dest,
            weight: weight,
        }
    }
}
impl std::cmp::Ord for Edge {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        (self.weight, self.src, self.dest).cmp(&(other.weight, other.src, other.dest))
    }
}
impl std::cmp::PartialOrd for Edge {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
type Edges = Vec<Edge>;
type Graph = Vec<Edges>;
#[allow(dead_code)]
fn graph_new(n: usize) -> Graph {
    vec![vec![]; n]
}
use std::collections::VecDeque;
// index ^ 1 is reverse edge
#[allow(dead_code)]
fn add_bi_edge(graph: &mut Graph, index: &mut usize, src: usize, dest: usize, weight: Weight) {
    graph[src].push(Edge::new(*index, src, dest, weight));
    *index += 1;
    graph[dest].push(Edge::new(*index, dest, src, weight));
    *index += 1;
}
#[allow(dead_code)]
fn add_uni_edge(graph: &mut Graph, index: &mut usize, src: usize, dest: usize, weight: Weight) {
    graph[src].push(Edge::new(*index, src, dest, weight));
    *index += 1;
    graph[dest].push(Edge::new(*index, dest, src, 0));
    *index += 1;
}

#[allow(dead_code)]
fn augment(
    g: &Graph,
    capacity: &mut Vec<Weight>,
    level: &Vec<usize>,
    finished: &mut Vec<bool>,
    from: usize,
    t: usize,
    cur: Weight,
) -> Weight {
    if from == t || cur == 0 {
        return cur;
    }
    if finished[from] {
        return 0;
    }
    for edge in g[from].iter() {
        let to = edge.dest;
        if level[to] != level[from] + 1 {
            continue;
        }
        let ncur = std::cmp::min(cur, capacity[edge.index]);
        let f = augment(g, capacity, level, finished, to, t, ncur);
        if f > 0 {
            capacity[edge.index] -= f;
            capacity[edge.index ^ 1] += f;
            return f;
        }
    }
    finished[from] = true;
    0
}

#[allow(dead_code)]
fn max_flow(g: &Graph, e: usize, s: usize, t: usize) -> Weight {
    let n = g.len();
    let mut capacity: Vec<Weight> = vec![0; e];
    for from in 0..n {
        for edge in g[from].iter() {
            capacity[edge.index] += edge.weight;
        }
    }
    let mut ans = 0;
    loop {
        let mut level = vec![usize::max_value(); n];
        level[s] = 0;
        let mut que = VecDeque::<usize>::new();
        que.push_back(s);
        while let Some(from) = que.pop_front() {
            if from == t {
                break;
            }
            for edge in g[from].iter() {
                let to = edge.dest;
                if capacity[edge.index] > 0 && level[to] == usize::max_value() {
                    que.push_back(to);
                    level[to] = level[from] + 1;
                }
            }
        }
        let mut finished = vec![false; n];
        let mut end = true;
        loop {
            let f = augment(
                g,
                &mut capacity,
                &level,
                &mut finished,
                s,
                t,
                Weight::max_value(),
            );
            if f == 0 {
                break;
            }
            ans += f;
            end = false;
        }
        if end {
            break;
        }
    }
    ans
}

fn main() {
    let n: usize = read();
    let mut seq = vec![0 as i64; n];
    for i in 0..n {
        seq[i] = read();
    }
    let mut g = graph_new(n + 2);
    let mut e = 0;
    let src = n;
    let dest = n + 1;
    let mut ans = 0;
    for from in 0..n {
        if seq[from] < 0 {
            add_uni_edge(&mut g, &mut e, src, from, seq[from].abs());
        } else {
            ans += seq[from];
            add_uni_edge(&mut g, &mut e, from, dest, seq[from].abs());
        }
        for i in 2..n + 1 {
            let to = (from + 1) * i - 1;
            if to >= n {
                break;
            }
            add_uni_edge(&mut g, &mut e, from, to, i64::max_value());
        }
    }
    // println!("{:?}", g);
    ans -= max_flow(&g, e, src, dest);
    println!("{}", ans);
}