1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| #include <queue> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define pii pair<int, int> #define con make_pair using namespace std; const int MAXN = 2e3 + 5; const int MAXM = 1e4 + 5; const int INF = 0x3f3f3f3f;
int n, m, st, ed, ans, tmp, mincost, mark[MAXN * MAXN], h[MAXN], pre[MAXN], flow[MAXN]; int tot = 1, head[MAXN], edge[MAXM], cost[MAXM], nxt[MAXM], ver[MAXM], dis[MAXN], cur[MAXN], d[MAXN]; queue<int> q; priority_queue<pii, vector<pii>, greater<pii> > que; bool vis[MAXN];
void AddEdge(int u, int v, int c, int w) { ver[++tot] = v, edge[tot] = c, cost[tot] = w, nxt[tot] = head[u], head[u] = tot; ver[++tot] = u, edge[tot] = 0, cost[tot] = -w, nxt[tot] = head[v], head[v] = tot; }
bool spfa(int st) {
while (!q.empty()) q.pop(); memset(vis, 0, sizeof(vis)); for (int i = 1; i <= 2 * m + 2; i++) dis[i] = INF;
dis[st] = 0, q.push(st), vis[st] = 1;
while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for (int i = head[u]; i; i = nxt[i]) { int v = ver[i]; if (!edge[i] || dis[v] <= dis[u] + cost[i]) continue; dis[v] = dis[u] + cost[i]; if (!vis[v]) { vis[v] = 1; q.push(v); } } }
for (int i = 1; i <= 2 * m + 2; i++) h[i] = dis[i];
return (dis[ed] < INF);
}
bool dijstra(int st) {
while (!que.empty()) que.pop(); for (int i = 1; i <= 2 * m + 2; i++) dis[i] = INF; memset(vis, 0, sizeof(vis)); memset(pre, 0, sizeof(pre));
que.push(con(0, st)), dis[st] = 0, flow[st] = INF;
while (!que.empty()) { int u = que.top().second; que.pop(); if (vis[u]) continue; vis[u] = 1; for (int i = head[u]; i; i = nxt[i]) { int v = ver[i]; if (!edge[i] || dis[v] <= dis[u] + cost[i] + h[u] - h[v]) continue; dis[v] = dis[u] + cost[i] + h[u] - h[v]; pre[v] = i; flow[v] = min(flow[u], edge[i]); que.push(con(dis[v], v)); } }
return (dis[ed] < INF);
}
int gcd(int x, int y) { if (y == 0) return x; else return gcd(y, x % y); }
bool check(int x, int y) { if (mark[y * y - x * x] != 0 && gcd(x, mark[y * y - x * x]) == 1) return true; else return false; }
int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= 1000; i++) mark[i * i] = i;
st = 2 * m + 1, ed = 2 * m + 2; for (int i = n; i <= m; i++) { AddEdge(st, i, 1, 0); AddEdge(i + m, ed, 1, 0); for (int j = i + 1; j <= m; j++) if (check(i, j)) { AddEdge(i, j + m, 1, -(i + j)); AddEdge(j, i + m, 1, -(i + j)); } }
spfa(st); while (dijstra(st)) { for (int i = 1; i <= 2 * m + 2; i++) h[i] = min(h[i] + dis[i], INF); ans += flow[ed]; mincost += flow[ed] * h[ed];
for (int i = ed; i != st; i = ver[pre[i] ^ 1]) { edge[pre[i]] -= flow[ed], edge[pre[i] ^ 1] += flow[ed]; }
} printf("%d %d\n", ans / 2, -mincost / 2);
return 0; }
|