1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 inline int read() 5 { 6 int x=0,f=1;char ch=getchar(); 7 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 8 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 9 return x*f; 10 } 11 12 13 /********************************************************************/ 14 15 struct ZKM_MinCostMaxFlow{ 16 const static int maxn = 1e5+50; 17 const static int maxE = 1e5+50; 18 const static int INF = 0xfffffff; 19 20 struct Edge{ 21 int to, next, cap, flow, cost; 22 Edge(int _to = 0, int _next = 0, int _cap = 0, int _flow = 0, int _cost = 0): 23 to(_to), next(_next), cap(_cap), flow(_flow), cost(_cost){} 24 }edge[maxE*2]; 25 26 int head[maxn], tot; 27 int cur[maxn], dis[maxn]; 28 bool vis[maxn]; 29 int ss, tt, N; 30 int min_cost, max_flow; 31 void init(int N){ 32 tot = 0; 33 for(int i = 0;i < N;i++) head[i] = -1; 34 } 35 int addedge(int u, int v, int cap, int cost){ 36 edge[tot] = Edge(v, head[u], cap, 0, cost); 37 int rs = tot; 38 head[u] = tot++; 39 edge[tot] = Edge(u, head[v], 0, 0, -cost); 40 head[v] = tot++; 41 return rs; 42 } 43 int aug(int u, int flow){ 44 if(u == tt) return flow; 45 vis[u] = true; 46 for(int i = cur[u];i != -1;i = edge[i].next){ 47 int v = edge[i].to; 48 if(edge[i].cap > edge[i].flow && !vis[v] && dis[u] == dis[v] + edge[i].cost){ 49 int tmp = aug(v, min(flow, edge[i].cap - edge[i].flow)); 50 edge[i].flow += tmp; 51 edge[i^1].flow -= tmp; 52 cur[u] = i; 53 if(tmp) return tmp; 54 } 55 } 56 return 0; 57 } 58 bool modify_label(){ 59 int d = INF; 60 for(int u = 0;u < N;u++){ 61 if(vis[u]){ 62 for(int i = head[u];i != -1;i = edge[i].next){ 63 int v = edge[i].to; 64 if(edge[i].cap > edge[i].flow && !vis[v]){ 65 d = min(d, dis[v]+edge[i].cost - dis[u]); 66 } 67 } 68 } 69 } 70 if(d == INF) return false; 71 for(int i = 0;i < N;i++){ 72 if(vis[i]){ 73 vis[i] = false; 74 dis[i] += d; 75 } 76 } 77 return true; 78 } 79 80 pair<int, int> mincostmaxflow(int start, int ed, int n){ 81 ss = start, tt = ed, N = n; 82 min_cost = max_flow = 0; 83 for(int i = 0;i < n;i++) dis[i] = 0; 84 while(1){ 85 for(int i = 0;i < n;i++) cur[i] = head[i]; 86 while(1){ 87 for(int i = 0;i < n;i++) vis[i] = false; 88 int tmp = aug(ss, INF); 89 if(tmp == 0) break; 90 max_flow += tmp; 91 min_cost += tmp*dis[ss]; 92 } 93 if(!modify_label()) break; 94 } 95 return make_pair( max_flow, min_cost ); 96 } 97 }solver; 98 99 int gcd(int x, int y){ 100 if(y == 0) return x; 101 else return gcd(y, x%y); 102 } 103 104 bool check(int x, int y){ 105 if(x == y) return false; 106 if(x < y) swap(x, y); 107 int t = sqrt(x*x-y*y); 108 if(t*t != x*x-y*y) return false; 109 if(gcd(y, t) != 1) return false; 110 return true; 111 } 112 113 int main(){ 114 int a, b; 115 a = read(); b = read(); 116 solver.init(b*2+5); 117 for(int i = a;i <= b;i++){ 118 for(int j = a;j <= b;j++){ 119 if(check(i, j)){ 120 solver.addedge(i, j+b, 1, -i-j); 121 } 122 } 123 solver.addedge(b*2+1, i, 1, 0); //拆点 124 solver.addedge(i+b, b*2+2, 1, 0); //拆点 125 } 126 pair<int, int> ans = solver.mincostmaxflow(b*2+1, b*2+2, b*2+5); 127 printf("%d %d ", ans.first/2, -ans.second/2); 128 return 0; 129 }