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 C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cassert>
#include <stack>
#include <limits>
#include <array>
#include <unordered_map>
#include <unordered_set>
#include <memory>
#include <numeric>
//#include <tuple>

constexpr long long mod = static_cast<long long>(1e9 + 7);

struct Edge {
    int to;
    long long capacity;
    int reverse;
};

std::vector<std::pair<int, int>> bfs(const std::vector<std::vector<Edge>>& edges) {
    std::vector<std::pair<int, int>> ans(edges.size(), std::make_pair(-1, -1)); //predecessor node and edge index
    std::queue<int> que;
    ans[0].first = 0;
    que.push(0);
    while(!que.empty()) {
        auto now = que.front();
        que.pop();
        if(now == edges.size() - 1)break;
        for(int i = 0; i < edges[now].size(); ++i) {
            auto& edge = edges[now][i];
            if(0 < edge.capacity && ans[edge.to].first < 0) {
                ans[edge.to].first = now;
                ans[edge.to].second = i;
                que.push(edge.to);
            }
        }
    }

    return ans;
}

long long updateNetwork(const std::vector<std::pair<int, int>>& predecesors, std::vector<std::vector<Edge>>& edges) {
    if(predecesors.back().first < 0) return 0;

    long long incr = std::numeric_limits<long long>::max();
    int v = predecesors.size() - 1;
    while(v != 0) {
        auto prev = predecesors[v].first;
        auto idx = predecesors[v].second;
        incr = std::min(incr, edges[prev][idx].capacity);
        v = prev;
    }

    v = predecesors.size() - 1;
    while(v != 0) {
        auto prev = predecesors[v].first;
        auto idx = predecesors[v].second;
        if(edges[prev][idx].capacity != std::numeric_limits<long long>::max()) {
            edges[prev][idx].capacity -= incr;
        }
        auto revNode = edges[prev][idx].to;
        auto revIdx  = edges[prev][idx].reverse;
        if(edges[revNode][revIdx].capacity != std::numeric_limits<long long>::max()) {
            edges[revNode][revIdx].capacity += incr;
        }
        v = prev;
    }

    return incr;
}

int main() {
    int N;
    std::cin >> N;

    std::vector<long long> a(N);
    for(auto& val: a)
        std::cin >> val;

    std::vector<std::vector<Edge>> edges(N + 2);
    for(int i = 0; i < N; ++i){
        if(a[i] > 0) {
            edges[i + 1].push_back(Edge{N + 1, a[i], (int)edges.back().size()});
            edges.back().push_back(Edge{i + 1, 0, (int)edges[i + 1].size() - 1});
        } else {
            edges.front().push_back(Edge{i + 1, -a[i], (int)edges[i + 1].size()});
            edges[i + 1].push_back(Edge{0, 0, (int)edges.front().size() - 1});
        }
    }

    for(int i = 1; i <= N; ++i) {
        for(int j = i + 1; j <= N; ++j) {
            if(j % i == 0) {
                edges[i].push_back(Edge{j, std::numeric_limits<long long>::max(), (int)edges[j].size()});
                edges[j].push_back(Edge{i, 0, (int)edges[i].size() - 1});
            }
        }
    }

    long long ans = 0;

    while(1){
        auto pred = bfs(edges);
        if(pred.back().first < 0) break;
        ans += updateNetwork(pred, edges);
    }

    long long sum = std::accumulate(begin(a), end(a), 0ll, [](long long init, long long x){ return x > 0 ? init + x : init; });

    std::cout << sum - ans << std::endl;

    return 0;
}