#include <iostream>
#include <vector>
#include <queue>
#include <limits>


//Dinic 法
//最大フロー最小カット問題を解くためのアルゴリズム
//ベルマン=フォード法で残滓パスを探す際に、レベルグラフを用いるもの



struct Dinic {


  struct Edge {
    // Edge 構造体
    // グラフの隣接リストの構成要素

    int to;  //行き先
    long long cost; //コスト
    int rev; //逆辺。G[to] vectorの何番目の辺が逆のEdgeなのかが記述してある。
    //残滓グラフを作るときに、逆向きの辺の容量を増やす作業が必要であるから、その時に検索をせずに済むように逆辺のリスト上の位置を記憶しておく。
  };

  // グラフ。隣接リストで表現している。
  std::vector<std::vector<Edge> > G;

  // レベルグラフ。Sから辺で何個分離れているかでラベルをつける。
  std::vector<int> level;

  // dfsをするときに、どの要素まで調べ終わっているかを記憶するイテレータ。これが無いとオーダーレベルで遅くなるらしい。
  std::vector<int> iter;

  Dinic(int n) {
    G.resize(n, std::vector<Edge>());
    level.resize(n, 0);
    iter.resize(n, 0);
  };

  void add_edge(int from, int to, long long cost) {
    G[from].push_back((Edge){to, cost, (int) G[to].size()}); //連接リストの何番目が逆辺なのかをrevに記述する
    G[to].push_back((Edge){from, 0, (int) G[from].size() - 1}); //上の要素はG[from] vectorのG[from].size() - 1番目
  };

  void create_level_graph(int s) {
    //bfsでlevel graphを作成する
    std::queue<int> que;

    //stack overflowによると、-03でmemsetと同速らしいので最適化はコンパイラに任せる
    std::fill(level.begin(), level.end(), -1);
    level[s] = 0;

    que.push(s);
    while(!que.empty()) {
      int v = que.front();

      que.pop(); //popは返り値がvoidでただ要素を消すのみなのでここで行う

      for(auto& edge: G[v]) {
        if(edge.cost > 0 && level[edge.to] < 0) {
          //(cost0は繋がってないedgeとみなす)
          level[edge.to] = level[v] + 1;
          que.push(edge.to);
        }
      }
    }
    return;
  };

  long long remove_shortest_aug_path(int v, int t, long long max_capacity) {
    //levelグラフを元に、dfsで最小の長さの増加パスを検索し、除去する。
    if(v == t) return max_capacity; //再起検索終了時
    
    for(int &i = iter[v]; i < G[v].size(); i++) {
      //iterで前回調べたパスを記憶しているので、そこから始める
      Edge &e = G[v][i];
      if(e.cost > 0 && level[v] < level[e.to]) {
        long long d = remove_shortest_aug_path(e.to, t, std::min(e.cost, max_capacity));
        if(d > 0) {
          //aug pathを除去
          e.cost -= d;
          G[e.to][e.rev].cost += d;
          return d;
        }
      }
    }
    //パスがない時
    return 0;
  };
  
  long long max_flow(int s, int t) {
    //s->tの最大フローを求める。
    long long flow = 0;
    const long long INF = std::numeric_limits<long long>::max();

    while(true) {
      //無限ループのように見えるが、1ループごとに最短のaug pathの長さが必ず増加するので、高々グラフのノード数(|V|)分しかループしない。
      create_level_graph(s);

      if(level[t] < 0) return flow;
      //グラフが分割された
      std::fill(iter.begin(), iter.end(), 0);
      long long f;
      while((f = remove_shortest_aug_path(s, t, INF)) > 0) {
        flow += f;
      }
    }
  }
};


int main(void) {
  //最小カット問題に帰着させる。
  //手順はnico_shindanさんの「燃やす埋める問題」についてのslideshareに載っている。

  //今回は、あるコストの宝石を「壊す」「壊さない」の小問題に、
  // 「i番目を壊したら必ずni番目も壊さなければならない」という制約が付いたタイプである。

  //従って、s-(壊さない)->(i番目の宝石)-(壊す)->t というパスを作った場合、
  //(i)->(ni) に向かって容量無限のパスを繋げれば良い

  //また最小カット問題の場合、グラフのコストが必ず正でなければならない。(負を含むとNP困難)
  //よって max_value = sum(min(0, (i番目の宝石のコスト))) とし、
  // max_valueからの損失をcostとしてパスを作る。
  // この時の各パスのコストは以下の通り
  //   壊さない | 壊す
  //i>0  0  | i
  //i<0  i  | 0
  int N;
  std::cin >> N;
  

  long long max_value = 0; //うまく壊せるときにもらえる最大の価値

  Dinic D(N+2);
  //sとtを含めて+2した。 sが0でtがN+1とする
  const int s = 0;
  const int t = N + 1;
  const long long INF = 1 << 30;
  if(INF < 0 && INF < 1000000000) std::cout << "INF < 0 :INF = " << INF << std::endl;

  for(int i = 1; i <= N; i++) {
    long long inp;
    std::cin >> inp;
    if(inp > 0) {
      D.add_edge(i, t, inp); //壊すと損失
      max_value += inp;
    } else {
      D.add_edge(s, i, -inp); //壊さないと損失
    }
    //iを壊すと倍数を叩き割らなければならない
    for(int j = 2 * i; j <= N; j += i) {
      D.add_edge(i, j, INF);
    }
  }

  long long flow = D.max_flow(s, t);
  /*
  for(auto x: D.G) {
    for(auto y: x) {
      std::cout << "to:" << y.to << "\tcost:" << y.cost << "\trev:" << y.rev << std::endl;
    }
  }
  */
  std::cout << max_value - flow << std::endl;
  return 0;
}


Measured memory_bytes: 256