……没啥可说的。最大权闭合子图,跑下dinic就好了……
#include <bits/stdc++.h> using namespace std; #define maxn 500000 #define int long long #define INF 99999999999LL int n, sum, S, T, lev[maxn]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * k; } struct edge { int cnp, to[maxn], f[maxn], last[maxn], head[maxn], cur[maxn]; edge() { cnp = 2; } void add(int u, int v, int fl) { to[cnp] = v, f[cnp] = fl, last[cnp] = head[u], head[u] = cnp ++; to[cnp] = u, f[cnp] = 0, last[cnp] = head[v], head[v] = cnp ++; } }E1; bool bfs() { memset(lev, 0, sizeof(lev)); queue <int> q; q.push(S); lev[S] = 1; while(!q.empty()) { int u = q.front(); q.pop(); for(int i = E1.head[u]; i; i = E1.last[i]) { int v = E1.to[i]; if(!lev[v] && E1.f[i]) { lev[v] = lev[u] + 1; q.push(v); } } if(lev[T]) return 1; } return 0; } int dfs(int u, int nf) { if(u == T) return nf; int tf = 0; for(int i = E1.cur[u]; i; i = E1.last[i]) { int v = E1.to[i]; if(lev[v] == lev[u] + 1 && E1.f[i]) { int af = dfs(v, min(nf, E1.f[i])); tf += af, nf -= af; E1.f[i] -= af, E1.f[i ^ 1] += af; if(!nf) return tf; E1.cur[u] = i; } } return tf; } int Dinic() { int ret = 0; while(bfs()) { memcpy(E1.cur, E1.head, sizeof(E1.head)); ret += dfs(S, INF); } return ret; } signed main() { n = read(); S = 0, T = n + 3; for(int i = 1; i <= n; i ++) { int x = read(); if(x > 0) sum += x, E1.add(i, T, x); else if(x <= 0) E1.add(S, i, -x); } for(int i = 1; i <= n; i ++) for(int j = 2; i * j <= n; j ++) if(i * j <= n) E1.add(i, i * j, INF); printf("%lld\n", sum - Dinic()); return 0; }