#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <random>

using namespace std;

#define DEBUG(x) cout<<#x<<": "<<x<<endl;
#define DEBUG_VEC(v) cout<<#v<<":";for(int i=0;i<v.size();i++) cout<<" "<<v[i]; cout<<endl

typedef long long ll;
#define vi vector<int>
#define vl vector<ll>
#define vii vector< vector<int> >
#define vll vector< vector<ll> >
#define vs vector<string>
#define pii pair<int,int>
#define pis pair<int,string>
#define psi pair<string,int>
const int inf = 1000000001;
const ll INF = 1e16;
#define MOD 1000000007
#define mod 1000000009
#define pi 3.14159265358979323846
#define Sp(p) cout<<setprecision(15)<<fixed<<p<<endl;
int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };
int dx2[8] = { 1,1,0,-1,-1,-1,0,1 }, dy2[8] = { 0,1,1,1,0,-1,-1,-1 };

#define int ll
// 辺を表す構造体 {行先、容量、逆辺}
struct edge { ll to, cap, rev; };
#define V 1010
int n;
int s, t; //sがstart, tがgoal
vector< vector<edge> > G(V, vector<edge>());; //グラフの隣接リスト表現
vector<bool> used(V); //DEFで調べたかのフラグ

					  //fromからtoへ向かう容量capの辺をグラフに追加する
void add_edge(ll from, ll to, ll cap) {
	edge a;
	a.to = to; a.cap = cap; a.rev = G[to].size();
	G[from].push_back(a);
	a.to = from; a.cap = 0; a.rev = G[from].size() - 1;
	G[to].push_back(a);
}

int dfs(int v, int t, ll f) {
	if (v == t) {
		return f;
	}
	used[v] = true;
	for (int i = 0; i < G[v].size(); i++) {
		edge &e = G[v][i];
		if (!used[e.to] && e.cap > 0) {
			ll d = dfs(e.to, t, min(f, e.cap));
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}

int max_flow(int s, int t) {
	int flow = 0;
	while (true) {
		fill(used.begin(), used.end(), false);
		ll f = dfs(s, t, INF);
		if (f == 0) return flow;
		flow += f;
	}
}

ll solve1(vl a2) {
	fill(used.begin(), used.end(), false);
	for (int i = 0; i < G.size(); i++) {
		G[i].clear();
	}
	vl a = a2;
	int i, j;
	ll sum = 0;
	for (i = 0; i < n; i++) {
		sum += max(a[i], 0LL);
	}
	for (i = 1; i <= n; i++) {
		for (j = 2; i*j <= n; j++) {
			add_edge(i, i*j, INF);
		}
	}
	for (i = 0; i < n; i++) {
		if (a[i] < 0) {
			add_edge(0, i + 1, -a[i]);
		}
		else {
			add_edge(i + 1, n + 1, a[i]);
		}
	}
	return sum - max_flow(0, n + 1);
}

ll solve2(vl a2) {
	int i, j;
	vl a(n + 1);
	ll sum = 0;
	for (i = 1; i <= n; i++) {
		a[i] = a2[i - 1];
		if (i >= n / 2 + 1) {
			a[i] = max(0LL, a[i]);
		}
		sum += a[i];
	}
	//DEBUG_VEC(a);
	//DEBUG(sum);
	vll b;
	vl s;
	s.push_back(sum);
	b.push_back(a);
	for (i = n / 2; i > 0; i--) {
		for (int k = 0; k < b.size(); k++) {
			if (b[k][i] < 0) {
				ll get = 0;
				for (j = 1; i*j <= n; j++) {
					get -= b[k][i*j];
				}
				if (get >= 0) {
					for (j = 1; i*j <= n; j++) {
						b[k][i*j] = 0;
					}
					s[k] += get;
				}
				else if (get == 0) {
					b.push_back(b[k]);
					s.push_back(s[k]);
					for (j = 1; i*j <= n; j++) {
						b[k][i*j] = 0;
					}
					s[k] += get;
				}
			}
		}
	}
	ll ans = -INF;
	for (i = 0; i < b.size(); i++) {
		ans = max(ans, s[i]);
	}
	return ans;
}


signed main() {
	std::random_device rnd;
	std::mt19937 mt(rnd());     //  メルセンヌ・ツイスタの32ビット版、引数は初期シード値
	std::uniform_int_distribution<> rand100(0, 10);        // [0, 99] 範囲の一様乱数
	cin >> n;
	vl a(n);
	while (true) {
		for (int i = 0; i < n; i++) {
			//a[i] = rand100(mt) - 5;
			cin >> a[i];
		}
		ll ans1 = solve1(a);
		ll ans2 = solve2(a);
		cout << ans1 << endl;
		return 0;
		cout << ans1 << " " << ans2 << endl;
		if (ans1 == ans2) {
			cout << "same" << endl;
		}
		else {
			cout << "different" << endl;
			DEBUG_VEC(a);
			return 0;
		}
	}
}



Measured memory_bytes: 256